特定情况下 firebase 的竞赛条件
Race around condition for particular case firebase
-uniqueid1
status:0
userTokenId: uniqueid(which is null)
我遇到了条件竞争问题,我不知道 firebase 如何实施这种情况。问题如下:
- 用户检查状态是否为 0。
- 如果状态为 0,它会将其令牌添加到 userTokenid 字段和状态 1
- 如果不是,那么它不会添加它的 tokenid。
现在的问题是当 2 个或更多用户检查状态 0 并且都输入 2 点时。这个问题可能毫无意义,但我需要确认。我需要担心这种情况吗?
firebase.child('uniqueid1');
firebase.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(datasnapshot.child('status').getValue().equals(0)){
//update record for userTokenId and status
}
else{
//don't update
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
如果两个客户端碰巧在大约同一时间通过 setValue()
或 updateChildren()
调用更新相同的值,则最后写入的优先。
如果您不想那样,您可能应该 using a transaction。来自该文档:
When working with complex data that could be corrupted by concurrent modifications, such as incremental counters, we provide a transaction operation. You give this operation two arguments: an update function and an optional completion callback. The update function takes the current state of the data as an argument and will return the new desired state you would like to write. For example, if we wanted to increment the number of upvotes on a specific blog post, we would write a transaction like the following:
Firebase upvotesRef = new Firebase("https://docs-examples.firebaseio.com/android/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes");
upvotesRef.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData currentData) {
if(currentData.getValue() == null) {
currentData.setValue(1);
} else {
currentData.setValue((Long) currentData.getValue() + 1);
}
return Transaction.success(currentData); //we can also abort by calling Transaction.abort()
}
@Override
public void onComplete(FirebaseError firebaseError, boolean committed, DataSnapshot currentData) {
//This method will be called once with the results of the transaction.
}
});
阅读 documentation on transaction()
了解完整详情。
Firebase ref=firebase.child("order_details/"+orderId);
ref.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData currentData) {
Log.d("status",currentData.getValue());
int status= (int) currentData.child("status").getValue();
if(status==0){
HashMap<String,Object> map=new HashMap<String, Object>();
map.put("TokenId",sharedPreferences.getString("tokenId",""));
map.put("status",1);
currentData.setValue(map);
}
((MapLoadingActivity)getActivity()).setProgressVisibility(false);
return Transaction.success(currentData);
}
@Override
public void onComplete(FirebaseError firebaseError, boolean b, DataSnapshot dataSnapshot) {
}
});
我知道问这个问题已经晚了,但是 doTransaction() 有时很奇怪,有时它只是简单地调用 returns null.Therefore 我通过调用 firebase 将我的方法切换为 php使用 php 包装器 class.Please 建议,如果我的方法是错误的。
-uniqueid1
status:0
userTokenId: uniqueid(which is null)
我遇到了条件竞争问题,我不知道 firebase 如何实施这种情况。问题如下:
- 用户检查状态是否为 0。
- 如果状态为 0,它会将其令牌添加到 userTokenid 字段和状态 1
- 如果不是,那么它不会添加它的 tokenid。
现在的问题是当 2 个或更多用户检查状态 0 并且都输入 2 点时。这个问题可能毫无意义,但我需要确认。我需要担心这种情况吗?
firebase.child('uniqueid1');
firebase.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(datasnapshot.child('status').getValue().equals(0)){
//update record for userTokenId and status
}
else{
//don't update
}
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
如果两个客户端碰巧在大约同一时间通过 setValue()
或 updateChildren()
调用更新相同的值,则最后写入的优先。
如果您不想那样,您可能应该 using a transaction。来自该文档:
When working with complex data that could be corrupted by concurrent modifications, such as incremental counters, we provide a transaction operation. You give this operation two arguments: an update function and an optional completion callback. The update function takes the current state of the data as an argument and will return the new desired state you would like to write. For example, if we wanted to increment the number of upvotes on a specific blog post, we would write a transaction like the following:
Firebase upvotesRef = new Firebase("https://docs-examples.firebaseio.com/android/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes");
upvotesRef.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData currentData) {
if(currentData.getValue() == null) {
currentData.setValue(1);
} else {
currentData.setValue((Long) currentData.getValue() + 1);
}
return Transaction.success(currentData); //we can also abort by calling Transaction.abort()
}
@Override
public void onComplete(FirebaseError firebaseError, boolean committed, DataSnapshot currentData) {
//This method will be called once with the results of the transaction.
}
});
阅读 documentation on transaction()
了解完整详情。
Firebase ref=firebase.child("order_details/"+orderId);
ref.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData currentData) {
Log.d("status",currentData.getValue());
int status= (int) currentData.child("status").getValue();
if(status==0){
HashMap<String,Object> map=new HashMap<String, Object>();
map.put("TokenId",sharedPreferences.getString("tokenId",""));
map.put("status",1);
currentData.setValue(map);
}
((MapLoadingActivity)getActivity()).setProgressVisibility(false);
return Transaction.success(currentData);
}
@Override
public void onComplete(FirebaseError firebaseError, boolean b, DataSnapshot dataSnapshot) {
}
});
我知道问这个问题已经晚了,但是 doTransaction() 有时很奇怪,有时它只是简单地调用 returns null.Therefore 我通过调用 firebase 将我的方法切换为 php使用 php 包装器 class.Please 建议,如果我的方法是错误的。