Firebase allows for a resource to be updated transactionally. As I understand it, the client does this buy sending requests to the server saying \"If the old value is X, ma
there is another way.... very tedious... and not really transactions...
As Firebase allows atomically changes on a value, you could create a lock or semaphore with the meaning of "started a transaction on the resources x, y and z"... of course, it is not a real transaction as it doesn't block resources, a part from the lock. We could call it transaction by convention. The clients needs to know that when the lock is occupied, they should not change x, y and z resources....
UPDATE
It's now possible to update multiple locations atomically. See this blog post for details.
var mergedUpdate = {};
mergedUpdate[ 'users/' + userId + '/widgets/' + widgetId ] = true;
mergedUpdate[ 'widgets/' + widgetId ] = widgetData;
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
ref.update(mergedUpdate);
This doesn't enforce transactional data (if value is currently X, make it Y), but this part can be moved to security rules. For example, if we want to update two counters at the same time, we could add rules as follows:
{
"counter1": {
".validate": "newData.val() === (data.val()||0)+1"
},
"counter2"1 {
".validate": "newData.val() === (data.val()||0)+1"
}
}
Now we can attempt the same multi-path update as above. If the values have changed since we last read them from the server, the attempt will fail. We can check if( error.code === 'PERMISSION_DENIED' ) { ... }
to see if the failure was due to validation, and retry accordingly.
ORIGINAL POST
The only way to do this is to run a transaction on a common ancestor.
For instance, if you want to update /a/b/c and /a/x/y, you could run a transaction at /a and change both of the values.
The downside to this approach is that it can be expensive with network I/O, as all of the data inside the transaction needs to be downloaded and then sent back to the server.
A more complicated but potentially more powerful approach you might want to consider is restructuring your data so that rather than storing the actual values, you store a history of the edits. For example, if you're storing bank balance information, you could store a history of deposits and withdrawals. Then when you wanted to get the balance, you would play back the whole history and calculate the end balance.
The beauty of this approach is it lets you do atomic updates. For example, if you were transferring money from accountA to accountB, you'd just append an element to the end of the log saying "transfer from account A to accountB N dollars". Appending that single element is an atomic operation.
This is the approach we take with Firepad, our collaborative text editor.