簡體   English   中英

AWS Amplify - 同步數據存儲

[英]AWS Amplify - sync DataStore

我正在嘗試構建一個原型應用程序來評估 AWS-Amplify (DataStore) 在我們的下一個應用程序中的使用。 嘗試同步 2 個客戶端時遇到問題。 我按照教程的說明設置了我的 AWS-DataStore: https://docs.amplify.aws/lib/datastore/getting-started/q/platform/ios使用 Cocoapods。 關於 Cocoapods 一切都按預期工作。 我嘗試了一些測試,也可以在上面的“操縱數據”鏈接下看到。 我還做了“將數據同步到雲”部分。 我可以在 AWS 控制台的 dynamoDB 中查看我的數據。 當我添加一個條目時,我可以在控制台中看到它一切都按預期工作,但在兩種情況下我遇到了問題:

假設我有 2 個客戶端 A 和 B(都運行 iOS 13 - 這里是真實設備還是在模擬器上都沒關系),我希望這些客戶端保持同步。 為此,我添加了一個 PostStore(我正在使用來自 atm 上方 AWS 鏈接的示例架構),如下所示:

import Foundation
import Combine
import SwiftUI
import Amplify

class PostStore: ObservableObject {
    
    @Published private(set) var posts: [Post] = []
    
    var postSubscription: AnyCancellable?
    
    init() {
        self.getAllPostsFromDataStore()
    }
    
    deinit {
        self.unsubscribeFromDataStore()
    }
    
    func getAllPostsFromDataStore() {
        
        Amplify.DataStore.query(Post.self) { (result) in
            switch result {
            case .success(let posts):
                DispatchQueue.main.async {
                    print("Got \(posts.count) Posts from DataStore initially")
                    self.posts = posts
                }
            case .failure(let error):
                print("Error getting Posts from DataStore: \(error.localizedDescription)")
            }
        }
    }
    
    func addRandomPostToDataStore() {
        
        let post = Post.getRandomPost()
        self.addPostToArray(post)
        
        print("Fire: \(post.id)")
        
        Amplify.DataStore.save(post) {
            
            switch $0 {
            case .success(let post):
                print("Added post with id: \(post.id)")
            case .failure(let error):
                print("Error adding post with title: \(post.title) Error: \(error.localizedDescription)")
            }
        }
    }
    
    func deletePostFromDataStore(for indexSet: IndexSet) {
        
        let postsToDelete = indexSet.map { self.posts[$0] }
        
        self.posts.remove(atOffsets: indexSet)
        
        for post in postsToDelete {
            
            Amplify.DataStore.delete(post) { (result) in
                switch result {
                case .success():
                    print("Deleted Post from DataStore")
                case .failure(let error):
                    print("Error deleting Post From DataStore: \(error)")
                }
            }
        }
    }
        
    func subscribeToDataStore() {
        
        postSubscription = Amplify.DataStore.publisher(for: Post.self)
            .sink(receiveCompletion: { (completion) in

                print("Completion!")

                if case .failure(let error) = completion {
                    print("Subscription received Error: \(error.localizedDescription)")
                }

            }, receiveValue: { (changes) in
                
                
                //print("Subscription received mutation: \(changes)")
                print("\n\n\n")
                print("\(try! changes.toJSON())")
                print("\n\n\n")
//                print("Changes!")
                let newPost = try! changes.decodeModel(as: Post.self)

                DispatchQueue.main.async {

                    switch changes.mutationType {
                    case "create":
//                        print("Create Subscription")
                        self.addPostToArray(newPost)
                        break
                    case "update":
                        print("Update Subscription")
                        self.updatePostInArray(newPost)
                        break
                    case "delete":
                        print("Delete Subscription")
                        self.deletePostFromArray(newPost)
                        break
                    default:
                        print("AnotherType?")
                        print(changes.mutationType)
                        break
                    }
                }
                print("\n")
            })
    }
    
    func unsubscribeFromDataStore() {
        postSubscription?.cancel()
    }
    
    private func addPostToArray(_ post: Post) {
        
        if !self.posts.contains(post) {
            self.posts.append(post)
        }
    }
    
    private func deletePostFromArray(_ post: Post) {
        
        if let index = self.posts.firstIndex(of: post) {
            self.posts.remove(at: index)
        }
    }
    
    private func updatePostInArray(_ post: Post) {
        print("update?")
    }
}

subscribeToDataStore方法是通過 SwiftUI-View(在onAppear中)觸發的,是這里的關鍵。 如果我向客戶端 A(緩慢地)添加一些帖子,那么客戶端 B 會收到所有更改並將其添加到商店(我使用 SwiftUI 視圖將其可視化,但在本示例中這無關緊要)。 這里沒有問題,一切都按預期工作。

  1. 當我使用客戶端 A 快速添加新條目(帖子)時,B 不會獲取一些新條目。
  2. 當我在客戶端 B 離線(處於飛行模式)時添加超過 1 個條目並且我關閉飛行模式時,每次訂閱只會獲取最新條目。

在這兩種情況下,當我觸發getAllPostsFromDataStore時,每個條目都會被獲取,我們再次對 go 很好。

所以我的問題是:為什么訂閱沒有獲取每一個條目?

執行場景 1 時有一個有趣的事實:接收每個訂閱條目時的常見日志消息如下所示:

WebsocketDidReceiveMessage - {MyObject}

然后我再次在接收器“receiveValue”完成中記錄 object:

{MyObject}

但是當快速(在短時間內)添加一些條目時,來自 Amplify 的日志消息有時看起來像這樣:(這是訂閱獲取中缺少第一個“對象”的地方):

WebsocketDidReceiveMessage - {MyObject}
WebsocketDidReceiveMessage - {MyObject2}

然后我再次在接收器“receiveValue”完成中記錄 object,並且只有最后一個 object 被記錄:

{MyObject2}

似乎{MyObject}在快速添加多個條目時被取消或發生了什么。 如上所述,當 B 處於飛行模式或沒有連接時,僅獲取最后添加的條目。 (但我也只收到WebsocketDidReceiveMessage的最后一條日志消息)。

我在這里遺漏了什么還是 Amplify-DataStore SDK 中的錯誤?

請原諒我的英語不好。 我不是母語人士,有時很難准確說出問題所在。 如果您對此問題有任何疑問或需要更多信息,請發表評論,我將編輯我的問題,提供您需要的一切。

此致

對於也遇到此問題的任何人:

在此處提交了一個問題,該問題似乎已在版本 1.3.1 中通過 PR #756得到修復

玩得開心!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM