How to properly cache outgoing messages?

Hello!

I have issues with the SyncManager. While all fetched / new incoming messages are cached correctly, my outgoing messages (both successfully sent, pending, and failed) disappear.

I do collection?.appendMessage(presendMessage) immediately after sending the message, and then collection?.handleSendMessageResponse(message, error) in the completionHandler block.

SBSMMessageCollectionDelegate callbacks work as expected – I see when pending, failed, and succeeded messages are inserted.

I’ve also noticed that in the sample SyncManager app handleSendMessageResponse(message, error) is never used. There’s another collection?.appendMessage(message) on its place. I’ve tried both versions, and it still doesn’t work for me.

SendBirdSDK (3.0.189)
SendBirdSyncManager (1.1.26)

Thank you!

@vlad Hello, I cannot reproduce the issue you described on sample code. So are you saying all out going messages (send by current user) disappear as soon as you send it?

Hello! The messages are sent correctly, and they are fetched with fetchAllNextMessages. However, they are not cached locally. If I send a message, then go offline, then reload the chat from cache – I see all messages except for the new ones that I’ve sent. Then I go back online, call fetchAllNewMessages on reconnection, and my messages are received and cached properly now. So, I have to manually call fetchAllNewMessages each time channel.sendUserMessage succeeds to force SyncManager to store my message because collection.appendMessage doesn’t work.

@vlad I see what you said. I will try to reproduce and see if I can find a cause.

@Woo thanks! If it works on your end, can you please share the exact steps on how to replicate your solution?

@vlad Would you mind to explain exact procedure you took to produce the result? how did you reload the chat from cache?

Hello @Woo

  1. I initialise the collection and fetch previous / next messages:
collection.fetch(in: .previous, completionHandler: { (hasMore, error) in
    collection.fetch(in: .next, completionHandler: { (hasMore, error) in

    })
})
  1. Then I send messages like this:
 func sendMessage(_ text: String) {
        var presendMessage: SBDBaseMessage?
        presendMessage = channel.sendUserMessage(text) { [weak self] (message, error) in
            if let error = error {
                print("Error sending message: \(error)")
                guard let presendMessage = presendMessage else { return }
                
                self?.presendMessages[presendMessage.requestId] = nil
                self?.resendableMessages[presendMessage.requestId] = presendMessage
                self?.generateChatItems()
                
                DispatchQueue.main.async {
                    self?.delegate?.chatItemsUpdated()
                }
            }
            else if let message = message {
                guard let presendMessage = self?.presendMessages[message.requestId],
                    let presendMessageIndex = self?.messages.firstIndex(of: presendMessage) else {
                    return
                }
                
                self?.presendMessages[message.requestId] = nil
                self?.messages[presendMessageIndex] = message
                self?.generateChatItems()
                
                DispatchQueue.main.async {
                    self?.delegate?.chatItemsUpdated()
                }
                
                // This is what's in the SyncManager sample app code
                self?.collection?.appendMessage(message)
            }
            
            // This is what's suggested on SendBird's website
            self?.collection?.handleSendMessageResponse(message, error)
        }
        
        if let presendMessage = presendMessage {
            presendMessages[presendMessage.requestId] = presendMessage
            messages.insert(presendMessage, at: 0)
            generateChatItems()
            
            DispatchQueue.main.async {
                self.delegate?.chatItemsUpdated()
            }
            
            collection?.appendMessage(presendMessage)
        }
    }

You mentioned reload the chat from cache after offline, how did you achieve that? I would like to know full procedure (step by step) you took. Thanks

@Woo I mean I send a message, it’s sent successfully (other users can see it), then I turn airplane mode on, then leave the chat page, open it again, initialize collection, fetch previous messages, fetch next messages – I see all messages except for the one that I’ve sent. Then I turn airplane mode off, and when the app reconnects to the SendBird server I call SBSMSyncManager.resumeSynchronize() and then fetchAllNewMessages inside didSucceedReconnection. Now my message is pushed to collection:didReceive:succeededMessages: and I insert it in the table view. After that if I repeat the same steps with turning airplane mode on, leaving the chat, opening it again – now I see all messages as they should be. Cached properly.

Got it! thanks for the explanation. Will let you know once I fix the problem

Hello @Woo ! Are there any updates on the issue? Thanks!

@vlad Hi! I found a solution and will release patch no later than next week. Next patch will include some of other fixes too. Thank you for your patient :slight_smile:

1 Like

Thanks @Woo, great to hear!

@vlad I just released v1.1.27 can you confirm the patch version fixes your problem? Thanks!

Hello @Woo yes, it works, thank you!