GV_FiQst
GV_FiQst

Reputation: 1567

Firebase ServerValue#TIMESTAMP with updateChildren()

I have this mapper which does the following:

override fun map(model: Model) = mapOf<String, Any?>(
  ...,
  KEY_TIMESTAMP to (model.timestamp.takeIf { it > -1 } ?: ServerValue.TIMESTAMP),
  ...
)

When I need to post some more models at the same time to different locations I take the mapper and use it to covert the model to Map<String, Any?>. So I have a bunch of maps which then are merged together to one big Map<String, Any?> It looks like this:

{
   "messages/-L_bXQUibioB6OMkl0SE/text": "Android Developer created this conversation",
   "messages/-L_bXQUibioB6OMkl0SE/senderName": "system",
   "messages/-L_bXQUibioB6OMkl0SE/senderAvatarUrl": null,
   "messages/-L_bXQUibioB6OMkl0SE/timestamp/.sv": "timestamp",
   "messages/-L_bXQUibioB6OMkl0SE/attachment": null,
   "chats/participants/UZ684hcHTnOkaglUX0QwbR9DK442/name": "cool guy",
   "chats/participants/UZ684hcHTnOkaglUX0QwbR9DK442/imageUrl": null,
   "chats/participants/aqiTRMAUOSdJIuEOvNJpeAb4D0F3/name": "Android Developer",
   "chats/participants/aqiTRMAUOSdJIuEOvNJpeAb4D0F3/imageUrl": "https://firebasestorage...",
   "chats/lastMessage": "Android Developer created this conversation",
   "chats/lastMessageTimestamp/.sv": "timestamp",
   "chats/name": null,
   "chats/imageUrl": null,
   "chats/type": "SINGLE"
}

So then I just do this:

ovveride fun updateChildren(data: Map<String, Any?>) = Completable.create { emitter ->
    rootRef.updateChildren(data) { databaseError, _ ->
        databaseError?.toException()
            ?.let(emitter::onError)
            ?: emitter.onComplete()
    }
}

When this last code is invoked I got the following exception:

com.google.firebase.database.DatabaseException: Path '/messages/-L_bXQUibioB6OMkl0SE/timestamp/.sv' contains disallowed child name: .sv
        at com.google.firebase.database.core.utilities.Validation.parseAndValidateUpdate(com.google.firebase:firebase-database@@16.0.5:140)
        at com.google.firebase.database.DatabaseReference.updateChildrenInternal(com.google.firebase:firebase-database@@16.0.5:428)
        at com.google.firebase.database.DatabaseReference.updateChildren(com.google.firebase:firebase-database@@16.0.5:418)

How can I fix this and still remain using ServerValue.TIMESTAMP if this is possible?

Upvotes: 0

Views: 86

Answers (1)

GV_FiQst
GV_FiQst

Reputation: 1567

It's because this line:

"messages/-L_bXQUibioB6OMkl0SE/timestamp/.sv": "timestamp"

should look like this:

"messages/-L_bXQUibioB6OMkl0SE/timestamp": {
    ".sv": "timestamp"
}

The bug was inside my map merging method The easiest workaround is to filter such properties:

lateinit var entry: MutableMap.MutableEntry<String, Any?>
while (map.entries.find { it.key.endsWith(".sv") }?.apply { entry = this } != null) {
    map.remove(entry.key)
    map[entry.key.removeSuffix("/.sv")] = ServerValue.TIMESTAMP
}

return realtimeDatabase.updateChildren(map)

Upvotes: 1

Related Questions