Firebase:如何以原子方式更新多个资源? [英] Firebase: How do I update multiple resources atomically?

查看:124
本文介绍了Firebase:如何以原子方式更新多个资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Firebase允许更新资源事务性。据我了解,客户端是否会向服务器发送请求,说如果旧的值是X,则创建新的值Y。如果存在争用,服务器可以拒绝来自客户端的多个更新,直到被接受。



现在,如果我想自动更新多个资源呢? 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.

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.

这篇关于Firebase:如何以原子方式更新多个资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆