在 中的版本化資料來源上使用 Delta Sync 操作 AWS AppSync - AWS AppSync

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

在 中的版本化資料來源上使用 Delta Sync 操作 AWS AppSync

注意

我們現在主要支援 APPSYNC_JS 執行期及其文件。請考慮在此處使用 APPSYNC_JS 執行期及其指南

透過將 GraphQL 回應快取至本機行動/網路應用程式中的磁碟,來 AWS AppSync 儲存資料的用戶端應用程式。已建立版本的資料來源和 Sync 操作可讓客戶使用單一解析程式來執行同步處理程序。透過這些查詢,用戶端可以使用從可能包含大量記錄的一個 base 查詢結果補充其本機快取,然後僅接收從上次查詢後有所更動的資料 (delta 更新)。藉由允許用戶端透過初始請求和其他請求的遞增性更新來執行快取的基本填入,所以您可將用戶端應用程式的計算工作移到後端。對於經常在上線和離線狀態之間切換的用戶端應用程式而言,這種做法可讓效率大幅提升。

若要實作 Delta Sync,Sync 查詢會在已建立版本的資料來源上使用 Sync 操作。當 AWS AppSync 突變變更版本控制資料來源中的項目時,該變更的記錄也會儲存在 Delta 資料表中。您可以選擇將不同的 Delta 資料表 (例如每種類型一個、每個網域區域一個) 用於其他版本控制的資料來源,或選擇將單一 Delta 資料表用於 API. AWS AppSync recommends,而不是將單一 Delta 資料表用於多個 APIs ,以避免主要金鑰發生衝突。

此外,Delta Sync 用戶端也可以透過引數接收訂閱,然後用戶端協調訂閱和重新連線,並在離線和線上轉換之間進行寫入。Delta Sync 會自動恢復訂閱來執行這個程序,包括指數退避、透過不同的網路錯誤案例進行抖動,以及將事件存放在佇列中。接著會先執行適當的 delta 或 base 查詢,再合併佇列中的任何事件,最後依照一般方式處理訂閱。

Amplify Framework 網站 DataStore提供用戶端組態選項的文件,包括 Amplify 。 https://aws-amplify.github.io/這份文件概述如何設定已建立版本的 DynamoDB 資料來源和 Sync 操作,以便與 Delta Sync 用戶端搭配使用,提供最佳的資料存取權。

一鍵設定

若要在 中自動設定 GraphQL 端點, AWS AppSync 並設定所有解析器和必要的 AWS 資源,請使用此 AWS CloudFormation 範本:

Blue button labeled "Launch Stack" with an arrow icon indicating an action to start.

這個堆疊會在您的帳戶中建立下列資源:

  • 2 個 DynamoDB 資料表 (基本和 Delta)

  • 1 AWS AppSync API 個含API金鑰

  • 1 個具有 DynamoDB 資料表政策IAM的角色

兩個資料表會用來將同步查詢分割成第二個資料表,並做為用戶端離線時遺漏事件的日誌。為了在 delta 資料表上保持查詢效率,Amazon DynamoDB TTLs 會視需要自動整理事件。TTL 時間可根據您的需求在資料來源上進行設定 (您可能想要 1 小時、1 天等)。

結構描述

若要示範 Delta Sync,範例應用程式會建立由 DynamoDB 中基礎Delta 資料表支援的 Posts 結構描述。 AWS AppSync 會自動將突變寫入兩個資料表。同步查詢會依適當情況從 BaseDelta 資料表提取記錄,並且定義一份訂閱,說明用戶端如何透過其重新連線邏輯來發揮變動功能。

input CreatePostInput { author: String! title: String! content: String! url: String ups: Int downs: Int _version: Int } interface Connection { nextToken: String startedAt: AWSTimestamp! } type Mutation { createPost(input: CreatePostInput!): Post updatePost(input: UpdatePostInput!): Post deletePost(input: DeletePostInput!): Post } type Post { id: ID! author: String! title: String! content: String! url: AWSURL ups: Int downs: Int _version: Int _deleted: Boolean _lastChangedAt: AWSTimestamp! } type PostConnection implements Connection { items: [Post!]! nextToken: String startedAt: AWSTimestamp! } type Query { getPost(id: ID!): Post syncPosts(limit: Int, nextToken: String, lastSync: AWSTimestamp): PostConnection! } type Subscription { onCreatePost: Post @aws_subscribe(mutations: ["createPost"]) onUpdatePost: Post @aws_subscribe(mutations: ["updatePost"]) onDeletePost: Post @aws_subscribe(mutations: ["deletePost"]) } input DeletePostInput { id: ID! _version: Int! } input UpdatePostInput { id: ID! author: String title: String content: String url: String ups: Int downs: Int _version: Int! } schema { query: Query mutation: Mutation subscription: Subscription }

這個 GraphQL 結構描述雖然是標準程序,但在繼續之前,有幾個事項值得我們提出說明。首先,所有變動會先自動寫入 Base 資料表,然後寫入 Delta 資料表。Base 資料表是狀態實況的中心來源,而 Delta 資料表是日誌記錄。如果您未在 中傳遞lastSync: AWSTimestampsyncPosts查詢會針對基礎資料表執行,並補充快取,以及定期執行 ,作為用戶端離線時間超過 Delta 資料表中設定TTL時間的邊緣案例的全域補充程序。如果您傳入 lastSync: AWSTimestampsyncPosts 查詢會執行處理您的 Delta 資料表,並由用戶端用來擷取自其上次離線後有所變更的事件。Amplify 用戶端會自動傳遞 lastSync: AWSTimestamp 值,並依適當情況儲存到磁碟中。

Post 上的 _deleted 欄位會用於DELETE操作。當用戶端離線且記錄已從 Base 資料表移除時,此屬性會通知用戶端執行同步處理,將記錄自其本機快取中移除。如果用戶端離線時間較長,而且在用戶端可以配合 Delta Sync 查詢來擷取這個值之前,該項目已先移除,則 Base 查詢 (可在用戶端中設定) 的全域更新事件將會執行,並從快取中移除該項目。此欄位會標記為選用項目,因為只有在執行同步查詢而結果出現已刪除的項目時,才會傳回值。

變動

對於所有突變, 會在基礎資料表中 AWS AppSync 執行標準Create/Update/Delete操作,也會自動在 Delta 資料表中記錄變更。您可以藉由在資料來源中修改 DeltaSyncTableTTL 值,以縮短或延長記錄保留時間。對於擁有高速資料的組織,應該會考慮縮短這段時間。或者,如果您的用戶端離線時間較長,最好設定較長的資料保留時間。

同步查詢

基本查詢是未指定lastSync值的 DynamoDB Sync 操作。這種做法適合許多組織,因為 Base 查詢只會在一開始時執行,且後續是定期執行。

Delta 查詢是指定lastSync值的 DynamoDB Sync 操作。每當離線用戶端恢復上線,就會執行 delta 查詢 (只要 base 查詢定期時間未觸發執行)。用戶端會自動追蹤上次成功執行查詢以同步資料的時間。

執行 delta 查詢時,查詢的解析程式會使用 ds_pkds_sk 僅查詢自上次用戶端執行同步以來變更的記錄。用戶端會存放適當的 GraphQL 回應。

如需有關執行同步查詢的詳細資訊,請參閱同步操作文件

範例

首先,藉由呼叫 createPost 變動來建立一個項目:

mutation create { createPost(input: {author: "Nadia", title: "My First Post", content: "Hello World"}) { id author title content _version _lastChangedAt _deleted } }

此變動的傳回值將如下所示:

{ "data": { "createPost": { "id": "81d36bbb-1579-4efe-92b8-2e3f679f628b", "author": "Nadia", "title": "My First Post", "content": "Hello World", "_version": 1, "_lastChangedAt": 1574469356331, "_deleted": null } } }

如果您檢查 Base 資料表的內容,您會看到一筆記錄,如下所示:

{ "_lastChangedAt": { "N": "1574469356331" }, "_version": { "N": "1" }, "author": { "S": "Nadia" }, "content": { "S": "Hello World" }, "id": { "S": "81d36bbb-1579-4efe-92b8-2e3f679f628b" }, "title": { "S": "My First Post" } }

如果您檢查 Delta 資料表的內容,您將會看見一筆記錄,如下所示:

{ "_lastChangedAt": { "N": "1574469356331" }, "_ttl": { "N": "1574472956" }, "_version": { "N": "1" }, "author": { "S": "Nadia" }, "content": { "S": "Hello World" }, "ds_pk": { "S": "AppSync-delta-sync-post:2019-11-23" }, "ds_sk": { "S": "00:35:56.331:81d36bbb-1579-4efe-92b8-2e3f679f628b:1" }, "id": { "S": "81d36bbb-1579-4efe-92b8-2e3f679f628b" }, "title": { "S": "My First Post" } }

現在,我們可以模擬 Base 查詢,客戶端將使用以下 syncPosts 查詢來執行該查詢以填入其本機資料存放區:

query baseQuery { syncPosts(limit: 100, lastSync: null, nextToken: null) { items { id author title content _version _lastChangedAt } startedAt nextToken } }

Base 查詢的傳回值將如下所示:

{ "data": { "syncPosts": { "items": [ { "id": "81d36bbb-1579-4efe-92b8-2e3f679f628b", "author": "Nadia", "title": "My First Post", "content": "Hello World", "_version": 1, "_lastChangedAt": 1574469356331 } ], "startedAt": 1574469602238, "nextToken": null } } }

稍後,我們將儲存 startedAt 值,以模擬 Delta 查詢,但需要先對資料表進行變更。讓我們使用 updatePost 變動以修改現有的 Post:

mutation updatePost { updatePost(input: {id: "81d36bbb-1579-4efe-92b8-2e3f679f628b", _version: 1, title: "Actually this is my Second Post"}) { id author title content _version _lastChangedAt _deleted } }

此變動的傳回值將如下所示:

{ "data": { "updatePost": { "id": "81d36bbb-1579-4efe-92b8-2e3f679f628b", "author": "Nadia", "title": "Actually this is my Second Post", "content": "Hello World", "_version": 2, "_lastChangedAt": 1574469851417, "_deleted": null } } }

如果您現在檢查 Base 資料表的內容,您應該會看見更新的項目:

{ "_lastChangedAt": { "N": "1574469851417" }, "_version": { "N": "2" }, "author": { "S": "Nadia" }, "content": { "S": "Hello World" }, "id": { "S": "81d36bbb-1579-4efe-92b8-2e3f679f628b" }, "title": { "S": "Actually this is my Second Post" } }

如果您現在檢查 Delta 資料表的內容,您應該會看到兩筆記錄:

  1. 建立項目時的記錄

  2. 更新項目時的記錄。

新項目如下所示:

{ "_lastChangedAt": { "N": "1574469851417" }, "_ttl": { "N": "1574473451" }, "_version": { "N": "2" }, "author": { "S": "Nadia" }, "content": { "S": "Hello World" }, "ds_pk": { "S": "AppSync-delta-sync-post:2019-11-23" }, "ds_sk": { "S": "00:44:11.417:81d36bbb-1579-4efe-92b8-2e3f679f628b:2" }, "id": { "S": "81d36bbb-1579-4efe-92b8-2e3f679f628b" }, "title": { "S": "Actually this is my Second Post" } }

現在,我們可以模擬 Delta 查詢,以擷取用戶端離線時發生的修改。我們將使用從基礎查詢傳回startedAt的值來提出請求:

query delta { syncPosts(limit: 100, lastSync: 1574469602238, nextToken: null) { items { id author title content _version } startedAt nextToken } }

Delta 查詢的傳回值將如下所示:

{ "data": { "syncPosts": { "items": [ { "id": "81d36bbb-1579-4efe-92b8-2e3f679f628b", "author": "Nadia", "title": "Actually this is my Second Post", "content": "Hello World", "_version": 2 } ], "startedAt": 1574470400808, "nextToken": null } } }