База данных Firebase Real-Time, что произойдет с одновременными запросами в этом случае?

У меня есть 2 узла в моей базе данных items и my_items.

У меня есть эта функция, которая выполняет multi-path update, эта функция удаляет элемент из items и добавляет его в my_items пользователя:

Я защитил узел my_items таким образом, что вы можете писать в него только в том случае, если элемент существует в items, в противном случае он не работает:

private void getItem(String uid, String item_key) {    
  Map<String, Object> updates = new HashMap<>();

  //delete item
  updates.put("items/" + item_key, null);

  //give the item to the user
  updates.put("my_items/" + uid + "/" + item_key, itemObject);

  mDatabaseReference.updateChildren(updates);
}

Вопрос (в теории):

  • Зная, что база данных Firebase обрабатывает запросы один за другим.

Если пользователи A, B, C, D одновременно вызвали функцию getItem(..) для одного и того же item id:

Имеет ли это смысл:

  1. скажем, запрос A первым достиг сервера и Succeeds

(теперь предмет удален из items и добавлен пользователю А в my_items)

  1. Б: Fails

(потому что предмет больше не существует в items, поэтому правило безопасности my_items предотвращает это)

  1. С: Fails

(та же самая причина)

  1. Д: Fails

(та же самая причина)

Это то, что произошло бы? Или я понял это неправильно?

Спасибо.

2
0
168
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В этой записи блога Firebase обсуждаются атомарные операции. RTDB обрабатывает запросы по мере их поступления. RTDB обрабатывает события по мере их поступления. Есть еще один вопрос, который может быть актуален Всегда ли Firebase гарантирует добавление событий по порядку?

Вы можете... сделать это в одном атомарном обновлении для обоих мест:

JavaScript

var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
// Generate a new push ID for the new post
var newPostRef = ref.child("posts").push();
var newPostKey = newPostRef.key();
// Create the data we want to update
var updatedUserData = {};
updatedUserData["user/posts/" + newPostKey] = true;
updatedUserData["posts/" + newPostKey] = {
  title: "New Post",
  content: "Here is my new post!"
};
// Do a deep-path update
ref.update(updatedUserData, function(error) {
  if (error) {
    console.info("Error updating data:", error);
  }
});

Джава

Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
// Generate a new push ID for the new post
Firebase newPostRef = ref.child("posts").push();
String newPostKey = newPostRef.getKey();
// Create the data we want to update
Map newPost = new HashMap();
newPost.put("title", "New Post");
newPost.put("content", "Here is my new post!");
Map updatedUserData = new HashMap();
updatedUserData.put("users/posts/" + newPostKey, true);
updatedUserData.put("posts/" + newPostKey, newPost);
// Do a deep-path update
ref.updateChildren(updatedUserData, new Firebase.CompletionListener() {
   @Override
   public void onComplete(FirebaseError firebaseError, Firebase firebase) {
       if (firebaseError != null) {
           System.out.println("Error updating data: " + firebaseError.getMessage());
       }
   }
});  

Цель-C

Firebase *ref = [[Firebase alloc] initWithUrl: @"https://<YOUR-FIREBASE-APP>.firebaseio.com"];
// Generate a new push ID for the new post
Firebase *newPostRef = [[ref childByAppendingPath:@"posts"] childByAutoId];
NSString *newPostKey = newPostRef.key;
NSString *updateUserPath = [NSString stringWithFormat:@"users/posts/%@", newPostKey];
NSString *updatePostPath = [NSString stringWithFormat:@"posts/%@", newPostKey];
// Create the data we want to update
NSMutableDictionary *updatedUserData = [[NSMutableDictionary alloc] init];
[updatedUserData setValue:[NSNumber numberWithBool:YES] forKey:updateUserPath];
[updatedUserData setValue:@{@"title": @"New Post", @"content": @"Here is my new post!"} forKey:updatePostPath];
// Do a deep-path update
[ref updateChildValues:updatedUserData withCompletionBlock:^(NSError *error, Firebase *ref) {
    if (error) {
        NSLog(@"Error updating data: %@", error.debugDescription);
    }
}];

Быстрый

"https://<YOUR-FIREBASE-APP>.firebaseio.com") // Generate a new push
ID for the new post let newPostRef =
ref.childByAppendingPath("posts").childByAutoId() let newPostKey =
newPostRef.key // Create the data we want to update let
updatedUserData = ["users/posts/(newPostKey)": true,
"posts/(newPostKey)": > ["title": "New Post", "content": "Here is my
new post!"]] // Do a deep-path update
ref.updateChildValues(updatedUserData, withCompletionBlock: { (error,
ref) -> > Void in
    if (error) {
        print("Error updating data: (error.description)")
    } }) 

Обновления глубокого пути позволяют писать более чистый код и легко денормализировать данные на нескольких узлах в вашей базе данных Firebase.

Мой вопрос не в том, как выполнить обновление с несколькими путями. Я просто хочу знать, имеет ли смысл приведенный выше пример с учетом правила безопасности, которое я написал

Data overflow 20.01.2023 01:03
Ответ принят как подходящий

База данных Firebase Realtime обрабатывает (записывает) операции последовательно. Таким образом, любая предыдущая операция записи будет завершена до того, как будет обработана следующая. Это означает, что любые данные, записанные предыдущим пользователем, действительно будут присутствовать в переменной root при оценке правил безопасности для последующих операций записи.

Большое спасибо, я понял, что вы сказали. Итак, согласно моей приведенной выше теории, верно ли, что независимо от того, сколько пользователей вызвали функцию, только один должен добиться успеха, а другие должны потерпеть неудачу?

Data overflow 22.01.2023 05:11

Это может зависеть от того, как вы реализуете правила. Я не хочу давать одеяло «ваш подход будет работать 👍» в абстрактном описании, следовательно, объясняя, как работает система. Изолированные многопользовательские операции определенно могут быть реализованы с транзакциями и/или обновлениями с несколькими путями и правилами безопасности, поэтому, если у вас возникнут проблемы, я рекомендую опубликовать новый вопрос с MCVE, и мы можем посмотреть.

Frank van Puffelen 22.01.2023 05:52

Спасибо Фрэнк за вашу помощь и за ваше время. Вскоре я спрошу, какое правило безопасности для items и my_items будет лучшим для достижения этой теории. Надеюсь, вы это проверите.

Data overflow 22.01.2023 08:48

Другие вопросы по теме