【问题标题】:Firebase rooms with limited number of participants参与者数量有限的 Firebase 房间
【发布时间】:2013-08-18 13:50:50
【问题描述】:

Firebase 中,创建诸如聊天之类的“房间”很容易,正如其各种示例中所记录的那样。

对于聊天的数据结构,我会使用这样的:

rooms
    room1
        member_count
        members
            user1
            user2
        messages
            message1

但现在我想创建一个限制每个房间的参与者数量,例如每个聊天室 3 个用户。

你怎么能做到这一点?

在他们的文档中,看起来最有希望的一件事是使用 transactions。你能证实这是一个好方法吗?还是这是错误的做法?

这样的解决方案怎么样?

Firebase countRef = new Firebase("https://mychat.firebaseIO-demo.com/rooms/room1");
countRef.runTransaction(new Transaction.Handler() {
    @Override
    public Transaction.Result doTransaction(MutableData currentData) {
        int oldMemberCount = currentData.child("member_count").getValue(Integer.class);
        currentData.child("member_count").setValue(oldMemberCount + 1); // try to update member count
        return Transaction.success(currentData);
    }

    @Override
    public void onComplete(FirebaseError error, boolean committed, DataSnapshot currentData) {
        if (error != null || !commited) {
            // rollback value (how? just do nothing?)
        }
        else {
            // transaction has been commited (value has already been saved?)
            currentData.child("members").child(CURRENT_USER_UUID).setValue(CURRENT_USER_NAME); // add user to the members list
        }
    }
});

如果您能对这种方法发表评论,那就太好了。此外,如果交易失败,当然不能满足于这种情况。用户仍然想加入,无论有其他用户同时尝试加入。那么做什么呢?把这段代码放到一个函数中,出错的时候再调用这个函数?

编辑:

要创建一个具有自动唯一 ID 的新房间,当然可以在 Firebase 引用上使用 push()

但是如果你想在那个房间里添加成员,那么上面描述的问题仍然存在。另一种解决方案是在加入时在成员列表中设置用户的priority。当将他们的优先级设置为当前时间戳时,可以limit 成员列表回调到 3(成员)。但这似乎既不优雅也不干净。

【问题讨论】:

  • 您不能只读取值 members_count,如果小于 3,则 'join' 否则 'abort'?
  • 不,如果两个客户端尝试同时加入,他们都会将 members_count 设置为 4 并加入。在那之后,房间里实际上会有 5 个客户。而且这种情况很可能出现在实时应用程序中,不是吗?
  • 如果你在他们连接之前做了检查,在他们连接之后你会没事的。如您所知,Firebase 不是 30 毫秒实时的。它们非常快,但不像您所说的 30 毫秒延迟。如果你那么快,你需要一个服务器,它执行逻辑而不使用 Firebase。但是一个可行的解决方案是你制定一个安全规则,如果val().children().length === 2 禁止写入。这将正常工作。
  • 您不需要 30 毫秒的实时数据来查看那里的冲突。使用 Firebase,客户端始终存储数据集的本地副本,然后自动与服务器版本同步。我没有编造这个例子,但 Firebase 确实明确暗示了这个问题,并建议在他们的文档中使用事务,正如我所发布的:firebase.com/docs/transactions.html 这绝对是要走的路。问题只是我提出的实现是否可行,因为它比 Firebase 在他们的文档中给出的简单示例要复杂一些。

标签: java android real-time firebase


【解决方案1】:

如果每个房间的参与者数量固定(且相对较少),最好使用事务处理。但是,最好为聊天室中的每个人创建命名良好的对象,例如:

/rooms
  /<roomid, generated by push()>
    /users
      one: null
      two: null
      three: null

加入房间的样子(JavaScript 代码,请酌情转换为 Java);

var userid = "myuserid";
var ref = new Firebase("<my-firebase>.firebaseio.com/rooms/<roomid>/users");
ref.transaction(function(users) {
  if (!users.one) {
    // Claim slot 1
    users.one = userid;
    return users;
  } else if (!users.two) {
    // Claim slot 2
    users.two = userid;
    return users;
  } else if (!users.three) {
    // Claim slot 3
    users.three = userid;
    return users;
  }
  // Room is full, abort the transaction.
  return;
}, function(err, committed, snapshot) {
  if (committed && !err) {
    // Joined room successfully.
  } else {
    // Could not join room because it was full.
  }
});

如果 Firebase 未能将值提交到服务器,它将自动调用事务函数。除了上面的代码之外,您还需要实现一些安全规则,以防止用户认领已被占用的插槽:

{
  "rules": {
    "rooms": {
      "$roomid": {
        "users": {
          "$slot": {
            ".write": "!data.exists()"
          }
        }
      }
    }
  }
}

您可以通过 Forge(Firebase 的图形调试器)上传这些规则,一切顺利!

【讨论】:

  • 非常感谢!这正是我的意思:) 但是为什么需要安全规则呢?从有关事务的文档(如果nobody else has modified it, the transaction is successful and your completion callback is called. Else, if there was a conflict, the Firebase client retrieves the new value and re-runs your update function)中,我了解到您可以只使用没有安全规则的事务,因为它们单独确保没有其他人修改数据。如果有人这样做,您首先会获得新值,然后可以再次检查房间是否为空。这是错的吗?
  • 我之所以这样问,是因为如果用户可以再次离开频道并且其他人可以申请他的位置,那将是非常好的。如果没有安全规则,这将是可能的。但是根据您的安全规则,您无法将自己从插槽中删除,因为一旦有数据,write 权限就会消失,对吧?
  • 没错,安全规则只是为了防止流氓客户端占据别人的位置。但是,正如您所指出的,这也意味着您不能将自己移出房间。您可以删除安全规则以允许这样做,或者如果您通过某种身份验证机制登录用户,您可以将规则更改为 "!data.exists() || auth.id == data.val() " 以确保只有声明了位置的用户才能删除自己。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-20
  • 1970-01-01
  • 2015-02-19
  • 2017-02-18
  • 2015-05-14
相关资源
最近更新 更多