I have an existing api admin code which I simplify for this for testing purposes (this works):
admin.database().ref('/dropbox').on('child_added', function (childSnap) { let item, itemRef = childSnap.ref; console.log(`Item: ${JSON.stringify(childSnap.val())} at ${childSnap.key}`); console.log(`Item ref: ${itemRef.toString()}`); itemRef.transaction(function (value) { console.log(`Value: ${JSON.stringify(value)}`); if (value) { item = value; return null; } }).then(function (resolution) { console.log(`Txn resolution: ${resolution.committed ? 'committed' : 'NOT-COMMITTED'}`); if (resolution.committed) {
When I run:
firebase database: push / dropbox <<'{"test": "abc123"}'
Console output:
Item: {"test":"abc123"} at -KgTpp3FzgbLUrMNofNZ Item ref: https://cloud-function-txn-test.firebaseio.com/dropbox/-KgTpp3FzgbLUrMNofNZ Value: {"test":"abc123"} Txn resolution: committed Process: {"test":"abc123"}
I am trying to move my code and this example to a cloud function. I understand that .on ('child_added', f) and .onWrite (f) process existing data differently, but I cannot get the transaction code to work correctly. The parameter passed to my transaction function is always zero.
Like a cloud function (this does not work):
exports.receiveAndRemove = functions.database.ref('/dropbox/{entryId}').onWrite(function (event) { if (!event.data.exists()) { return; } let item, itemRef = event.data.adminRef; console.log(`Item: ${JSON.stringify(event.data.val())} at ${event.data.key}`); console.log(`Item ref: ${itemRef.toString()}`); itemRef.transaction(function (value) { console.log(`Value: ${JSON.stringify(value)}`); if (value) { item = value; return null; } }).then(function (resolution) { console.log(`Txn resolution: ${resolution.committed ? 'committed' : 'NOT-COMMITTED'}`); if (resolution.committed) {
For some reason, a transaction never deletes an item. Log output:
2017-03-30T10:51:19.387565284ZD receiveAndRemove: Function execution started 2017-03-30T10:51:19.395ZI receiveAndRemove: Item: {"test":"abc123"} at -KgTpp3FzgbLUrMNofNZ 2017-03-30T10:51:19.395ZI receiveAndRemove: Item ref: https://cloud-function-txn-test.firebaseio.com/dropbox/-KgTpp3FzgbLUrMNofNZ 2017-03-30T10:51:19.396ZI receiveAndRemove: Value: null 2017-03-30T10:51:19.396ZI receiveAndRemove: Txn resolution: NOT-COMMITTED 2017-03-30T10:51:19.418446269ZD receiveAndRemove: Function execution took 32 ms, finished with status: 'ok'
Of course, the cloud function does not delete the element, and since the transaction does not perform the deletion, it also does not process the element. I expect this to happen, and I expect this code to work even if the node server version is running. Elements should always be processed exactly once no matter how many instances are running in the cloud and / or on my server.
Is there any subtle difference in the cloud features that I am missing? Is there something that I am doing with transactions incorrectly or that does not work with cloud functions?
Full source: https://github.com/mscalora/cloud-function-txn-test.git