0

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 的新房间,当然可以在引用上使用push() 。Firebase

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

4

1 回答 1

2

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

/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 的图形调试器)上传这些规则,您应该一切顺利!

于 2013-08-19T23:44:34.547 回答