Firebase并发锁定/解锁写访问多个设备

时间:2019-05-15 21:39:04

标签: java android firebase

我正在寻找有关如何在从多个设备进行android的并发访问中锁定/解锁firebase的写访问的提示

我希望能够做这样的事情:

  • 获得写访问权限并锁定
  • 可运行过程->从Firebase获取一些数据,对其进行处理
  • 可运行过程->从先前的可运行过程中获取数据,将一些数据写入Firebase
  • 可运行过程->从另一个可运行过程中获取数据,获取另一个数据,对其进行处理
  • 可运行的过程->写一些数据
  • 等等
  • 任务执行所有同步可运行的操作,将一堆数据写入firebase
  • 解锁写访问权限

我的第一个想法是增加超时。如果您未在允许的数量之前解锁,则锁定写操作可能会单独失效,以确保没有设备可以阻止访问。

我阅读了有关交易的信息,但我认为它不适合我的需求。因为我在处理时需要访问多个路径。

在任何人都知道如何实现设备必须先获得才能进行写入的锁定/解锁写入访问权限?

感谢任何想法。

PS:我的可运行同步任务已经很好地完成了工作,我只是在寻找如何锁定和解锁Firebase的写访问权限,以确保在处理某些数据时没有其他设备可以破坏数据。

3 个答案:

答案 0 :(得分:1)

实时数据库和Cloud Firestore都没有一种机制,您可以在处理数据库时在任意时间内强制锁定整个数据库,甚至只是其中一部分。这样的事情根本无法在现实世界中扩展。

这两个数据库都提供事务处理机制,这是原子地,一致地执行读写的唯一方法。如果您绝对需要其他形式的锁定,则云托管数据库可能不是您的最佳选择。要么,要么通过您控制的单个中间件来集中所有访问,但这种中间件也无法很好地扩展。

答案 1 :(得分:1)

因此,实际上,有一种方法。道格(Doug),在没有答案之前,也许您应该尝试打开思路,而不是直接寻求快速答案。

如何操作: -使用交易 -在所需的补丁程序中读取条目并锁定所需的补丁程序,条目为guid +设备的时间戳。 -如果时间戳<小于您的时间戳,则说明补丁未锁定,您可以通过编写GUID和时间戳+需要锁定的时间来获取补丁。 -当交易成功时,您就是赢家,可以做任何您想做的事情。 -完成后,写入当前时间戳以释放锁定

答案 2 :(得分:1)

如果有人需要它,这就是我如何在特定路径3s上获取并获得一个锁的方法。 -在每个表(路径)上,您可以将一个tableInfo关联起来,其中包含该路径的锁。 -如果没有其他人需要锁,则获取,释放并延长时间。您可以在尝试获取此锁的其他设备的GUID的另一个字段上添加侦听器。而且很高兴实现它,而不是延长您的时间。

fbBase.child(tableInfoChildRef).child(TableInfo.Field.Lock.name).runTransaction(new Transaction.Handler() {
                public Map<String, Object> lock(){
                    Map<String, Object> data = new ArrayMap<>();
                    data.put(TableInfo.Field.Lock.guid, AppGUID.get().toString());
                    data.put(TableInfo.Field.Lock.timestamp, System.currentTimeMillis()+3000);
                    return data;
                }

                @NonNull
                @Override
                public Transaction.Result doTransaction(@NonNull MutableData mutableData) {

                    if(mutableData.getValue() == null) {
                        mutableData.setValue(lock());
                        return Transaction.success(mutableData);
                    }else{
                        Long lockTimestamp = mutableData.child(TableInfo.Field.Lock.timestamp).getValue(Long.class);
                        if(lockTimestamp < System.currentTimeMillis()){
                            mutableData.setValue(lock());
                            return Transaction.success(mutableData);
                        }
                    }
                    return Transaction.abort();
                }

                @Override
                public void onComplete(@Nullable DatabaseError databaseError, boolean b, @Nullable DataSnapshot dataSnapshot) {
                    if(b) LogDelay.send("WIN");
                    else LogDelay.send("LOSE");
                }
            });