Firebase:如何以原子方式更新多个资源? [英] Firebase: How do I update multiple resources atomically?
问题描述
现在,如果我想自动更新多个资源呢? b
$ b
如果第一次更新被接受,会发生什么情况,然后客户端在第二次更新被接受之前断开连接。有没有办法在一个原子事务中包含多个更新?如果没有,是否有这种问题的习惯性解决方案?
更新
b$ b
现在可以以原子方式更新多个位置。有关详细信息,请参阅此博客文章。
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);
这不强制执行事务性数据(如果当前值为X,则为Y)部分可以移动到安全规则。例如,如果我们想同时更新两个计数器,我们可以添加如下规则:
{
counter1:{
.validate:newData.val()===(data.val()|| 0)+1
,
counter21 {
.validate:newData.val()===(data.val()|| 0)+1
}
现在我们可以尝试与上面相同的多路径更新。如果自从我们上次从服务器读取这些值之后这些值已经发生变化,则尝试将失败。我们可以检查 if(error.code ==='PERMISSION_DENIED'){...}
来查看失败是否由验证引起,并相应地重试。 >
ORIGINAL POST
要做到这一点,唯一的方法是在一个公共祖先。例如,如果你想更新/ a / b / c和/ a / x / y,你可以在/ a上运行一个事务并且改变这两个价值。
这种方法的不足之处在于,对于网络I / O来说可能会很昂贵,因为交易中的所有数据都需要下载并发回到服务器。
一个更复杂,但可能更强大的方法,你可能要考虑的是重构你的数据,而不是存储实际值,你存储的历史编辑。例如,如果您要存储银行余额信息,则可以存储存款和取款的历史记录。然后,当你想获得平衡,你会回放整个历史和计算结束余额。
这种方法的美妙之处是它可以让你做原子更新。例如,如果您从账户A转账到账户B,您只需在日志末尾追加一个元素,即从账户A转账到账户N元。追加单个元素是一个原子操作。
这是我们用 Firepad < a>,我们的协作文本编辑器。 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, make the new value Y". If there is contention the server could reject multiple updates form the client until one is accepted. Now, what if I want to update multiple resources atomically? What happens if the first update is accepted, and then the client is disconnected prior to the second update being accepted. Is there any way to enclose multiple updates in an atomic transaction? If not, is there an idiomatic solution to this problem? UPDATE It's now possible to update multiple locations atomically. See this blog post for details. 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: 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 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. 这篇关于Firebase:如何以原子方式更新多个资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!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);
{
"counter1": {
".validate": "newData.val() === (data.val()||0)+1"
},
"counter2"1 {
".validate": "newData.val() === (data.val()||0)+1"
}
}
if( error.code === 'PERMISSION_DENIED' ) { ... }
to see if the failure was due to validation, and retry accordingly.