教學課程:在版本化的資料來源上使用差異同步作業 - AWS AppSync

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

教學課程:在版本化的資料來源上使用差異同步作業

注意

我們現在主要支援 APPSYNC _JS 執行階段及其文件。請考慮在此處使用 APPSYNC _JS 運行時及其指南

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

若要實作 Delta Sync,Sync 查詢會在已建立版本的資料來源上使用 Sync 操作。當變 AWS AppSync 異變更版本化資料來源中的項目時,該變更的記錄也會儲存在 Delta 資料表中。您可以選擇為其他版本化資料來源使用不同的 Delta 表格 (例如,每個類型一個,每個網域區域一個),或為您API的. AWS AppSync 建議不要對多個使用單個 Delta 表,APIs以避免主鍵的衝突。

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

用戶端設定選項 (包括 Amplify DataStore) 的說明文件可在 A mplify 架構網站上取得。這份文件概述如何設定已建立版本的 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 表格 (基本和差異)

  • 1 個 AWS AppSync API帶API鑰匙

  • 1 具有 DynamoDB 資料表原則的IAM角色

兩個資料表會用來將同步查詢分割成第二個資料表,並做為用戶端離線時遺漏事件的日誌。為了讓查詢在差異表上保持TTLs有效率,Amazon DynamoDB 會根據需要自動調整事件。TTL時間可根據您對數據源的需求進行配置(您可能希望將其設置為 1 小時,1 天等)。

結構描述

為了示範差異同步,範例應用程式會在 DynamoDB 中建立由基礎異資料表支援的 Poss 結構描述。 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查詢會針對 Base 資料表執行,並加入快取,並在定期時執行,做為邊緣案例的全域追趕程序,當用戶端離線時間超過您在 Delta 資料表中設定的TTL時間時間。如果您傳入 lastSync: AWSTimestampsyncPosts 查詢會執行處理您的 Delta 資料表,並由用戶端用來擷取自其上次離線後有所變更的事件。Amplify 用戶端會自動傳遞 lastSync: AWSTimestamp 值,並依適當情況儲存到磁碟中。

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

變動

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

同步查詢

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

差異查詢是具有指lastSync定值的 DynamoDB 同步作業。每當離線用戶端恢復上線,就會執行 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 查詢,以擷取用戶端離線時發生的修改。我們將使用從我們的 Base 查詢返回的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 } } }