【发布时间】: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