ios – 复杂写入的Firebase提交/回滚

前端之家收集整理的这篇文章主要介绍了ios – 复杂写入的Firebase提交/回滚前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用Firebase编写财务应用程序,并且要提交收据,还需要更新许多其他对象.要使数据有效,需要成功完成所有数据更新.如果其中一个写入出现错误,则必须回滚所有更新.

例如:

如果用户提交收据,则必须更新收货对象以及发票对象以及其他总帐对象.

如果更新已开始但用户中途失去了互联网连接,则应回滚所有更改.

在Firebase中实现这一目标的最佳方法是什么?

解决方法

首先,让我们聊聊一下为什么有人可能想要在多个数据路径上进行提交/回滚…

你需要这个吗?

通常,如果符合以下条件,则不需要此:

>你不是用高并发性写的(DIFFERENT用户每分钟写入数百次写入操作)
>你的依赖是直截了当的(B取决于A,C取决于A,但A不依赖于B或C)
>您的数据可以合并为一个路径

开发人员对他们的数据中出现的孤立记录有点过于担心.
Web套接字在一次写入和另一次写入之间失败的可能性可能微不足道,并且在某些地方之间发生冲突
基于时间戳的ID.这并不是说这是不可能的,但它通常是低后果,极不可能,并且不应该是你的主要关注点.

此外,使用脚本甚至只需在JS控制台中输入几行代码即可轻松清理孤儿.再一次,
它们的后果往往很低.

你可以做什么而不是这个?

将必须以原子方式写入的所有数据放入单个路径中.然后,如果需要,您可以将其写为单个settransaction.

或者在一个记录是主记录而其他记录依赖于此的情况下,只需先写入主记录,然后在回调中写入其他记录.添加安全规则以强制执行此操作,以便在允许其他人写入之前始终存在主记录.

如果要简化数据的规范化以简化和快速迭代(例如,获取用户名称列表),那么只需在单独的路径中索引该数据.
然后,您可以在单个路径中获取完整的数据记录,并在快速查询/排序友好列表中包含名称,电子邮件等.

什么时候有用?

如果您有一组非规范化的记录,则可以使用此工具:

>实际上不能将实际合并到一条路径中
>具有复杂的依赖关系(A取决于C,C取决于B,B取决于A)
>记录以高并发性写入(即,每分钟可能有数百个写操作由不同用户的SAME记录)

你怎么做到这一点?

我们的想法是使用更新计数器来确保所有路径都保持相同的版本.

1)创建一个使用事务递增的更新计数器:

function updateCounter(counterRef,next) {
   counterRef.transaction(function(current_value) {
      return (current_value||0)+1;
   },function(err,committed,ss) {
      if( err ) console.error(err)
      else if( committed ) next(ss.val());
   },false);
}

2)给它一些安全规则

"counters": {
   "$counter": {
      ".read": true,".write": "newData.isNumber() && ( (!data.exists() && newData.val() === 1) || newData.val() === data.val() + 1 )"
   }
},

3)提供记录安全规则以强制执行update_counter

"$atomic_path": {
   ".read": true,// .validate allows these records to be deleted,use .write to prevent deletions
   ".validate": "newData.hasChildren(['update_counter','update_key']) && root.child('counters/'+newData.child('update_key').val()).val() === newData.child('update_counter').val()","update_counter": {
      ".validate": "newData.isNumber()"
   },"update_key": {
      ".validate": "newData.isString()"
   }
}

4)使用update_counter写入数据

由于您具有安全规则,因此只有在计数器不移动时,记录才能成功写入.如果它确实移动,则记录已被并发更改覆盖,因此它们不再重要(它们不再是最新且最好的).

var fb = new Firebase(URL);

updateCounter(function(newCounter) {
   var data = { foo: 'bar',update_counter: newCounter,update_key: 'myKey' };
   fb.child('pathA').set(data);
   fb.child('pathB').set(/* some other data */);
   // depending on your use case,you may want transactions here
   // to check data state before write,but they aren't strictly necessary
});

5)回滚

回滚涉及更多,但可以建立这个原则:

>在调用set之前存储旧值
>监控每组操作失败
>在任何已提交的更改中设置回旧值,但保留新计数器

预建的图书馆

我今天写了一篇文章来做这个和stuffed it on GitHub.随意使用它,但请确保你没有通过阅读“你需要这个吗?”让你的生活变得复杂.以上.

原文链接:https://www.f2er.com/iOS/334715.html

猜你在找的iOS相关文章