Firebase: как использовать функцию observSingleEventOfType для получения последних данных сервера при включенной поддержке?

Мне очень нравится кодирование с Firebase. Это отличный бэкэнд с множеством различных наборов инструментов. Но я пропустил простой способ проверить путь для обновленных данных, когда включено. Я думаю, что это не редкость, потому что мне часто нужно, чтобы мое приложение действовало определенным образом в зависимости от последних данных сервера, которые нужно читать только один раз.

Обычно я использую observeSingleEventOfType, но это бесполезно, когда разрешена поддержка, так как никогда не будет извлекать последние данные сервера. Который я не понимаю, почему. Должна быть добавлена ​​опция, чтобы пропустить локальный кеш и посмотреть только данные сервера.

Отключение стойкости решает эту проблему, а observeSingleEventOfType будет работать, как ожидалось. Но это означало бы, что нужно полностью реализовать все автономные возможности самостоятельно.

Первый сценарий:

 // chats contain meta information about the chat like last message and count of unread messages

 let chatRef = ref.child("chats").child(receiverId).child(chatId)
 chatRef.observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
     if !snapshot.exists() {
         print("snapshot does not exist")
         // the other side has deleted the chat
         // now delete all messages and member objects

         ref.child("messages").child(chatId).setValue(nil)
         ref.child("members").child(chatId).setValue(nil)
     } else {
         print("snapshot exists")
     }
 })

Я также пробовал chatRef.keepSynced(true), прежде чем наблюдать за событиями без везения. В любом случае это не имеет смысла во всех ситуациях:

Второй сценарий:

func removeOlderMessages() {
    let dateInThePast = NSDate().addDays(-30).timeIntervalSince1970 * 1000
    self.messagesRef.queryOrderedByChild("timestamp")
        .queryEndingAtValue(dateInThePast)
        .observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in
            snapshot.ref.removeValue()
    })
}

Использование keepSynced здесь приведет к загрузке всех сообщений в messagesRef, что совсем не требуется.

Итак, есть ли умное решение для этих двух сценариев? Любая помощь приветствуется.

Ответ 1

Хорошо, думаю, я нашел разумное решение для обоих сценариев:

Обходной путь для первого сценария:

Используйте transactions. Они будут работать только в режиме онлайн. Блок completition будет возвращать последние данные сервера.

self.ref.child("chats").child(receiverId).child(chatId).runTransactionBlock({ (currentData) -> FIRTransactionResult in
    // Actually do nothing with the retrieved data and re-submit it.
    return FIRTransactionResult.successWithValue(currentData)
 }) { (error, success, snapshot) in

    if let error = error {
        print(error)
        return
    } else if !success || snapshot == nil {
       return
    }

    // snapshot contains the latest server data
    if !snapshot!.exists() {
       // the other side has deleted the chat
       // now delete all messages and member objects

       print("snapshot doesn't exist. deleting messages and members.")
       ref.child("messages").child(chatId).setValue(nil)
       ref.child("members").child(chatId).setValue(nil)     
    } else {
       print("snapshot exists. not deleting all messages and members.")
    }     
}

Недостатком является то, что для получения данных потребуется значительно больше времени, чем observeEventType или observeSingleEventOfType.

Обходной путь для второго сценария:

Используйте observeEventType(.Value). Сначала он будет возвращать кэшированные, а затем последние данные сервера, если они доступны. Наблюдатель может быть удален после заданного интервала времени с NSTimer.

Во всех этих обходных решениях все нормально, но функция пропустить локальный кеш при использовании observeSingleEventOfType является незаменимой.