Подтвердить что ты не робот

Firebase: Как я могу атомизировать несколько ресурсов?

Firebase позволяет обновлять ресурс транзакционно. Как я понимаю, клиент делает это, покупая запросы отправки на сервер, говоря: "Если старое значение X, сделайте новое значение Y". Если есть разногласия, сервер может отклонить несколько обновлений от клиента до тех пор, пока не будет принято.

Теперь, если я хочу атомизировать несколько ресурсов?

Что произойдет, если первое обновление будет принято, а затем клиент будет отключен до того, как будет принято второе обновление. Есть ли способ заключить несколько обновлений в атомную транзакцию? Если нет, существует ли идиоматическое решение этой проблемы?

4b9b3361

Ответ 1

UPDATE

Теперь можно обновлять несколько мест атомарно. Подробнее см. этот пост в блоге.

var mergedUpdate = {};
mergedUpdate[ 'users/' + userId + '/widgets/' + widgetId ] = true;
mergedUpdate[ 'widgets/' + widgetId ] = widgetData;

var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
ref.update(mergedUpdate);

Это не обеспечивает выполнение транзакционных данных (если в настоящее время значение X, сделайте Y), но эту часть можно перенести в правила безопасности. Например, если мы хотим одновременно обновить два счетчика, мы можем добавить следующие правила:

{
  "counter1": {
     ".validate": "newData.val() === (data.val()||0)+1"
  },

  "counter2"1 {
     ".validate": "newData.val() === (data.val()||0)+1"
  }
}

Теперь мы можем попробовать одно и то же многоканальное обновление, как указано выше. Если значения изменились с момента последнего их чтения с сервера, попытка завершится неудачно. Мы можем проверить if( error.code === 'PERMISSION_DENIED' ) { ... }, чтобы увидеть, произошел ли отказ из-за проверки, и повторите попытку.

ОРИГИНАЛЬНАЯ ПОЧТА

Единственный способ сделать это - запустить транзакцию для общего предка.

Например, если вы хотите обновить /a/b/c и/a/x/y, вы можете запустить транзакцию в /a и изменить оба значения.

Недостатком этого подхода является то, что он может быть дорогостоящим с сетевым вводом/выводом, так как все данные внутри транзакции должны быть загружены, а затем отправлены обратно на сервер.

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

Красота этого подхода заключается в том, что он позволяет выполнять атомарные обновления. Например, если вы переводили деньги с accountA на accountB, вы просто добавляли элемент в конец журнала, говоря "перевод с учетной записи A на счет B N долларов". Добавление этого единственного элемента - это атомная операция.

Это подход, который мы используем с Firepad, нашим совместным текстовым редактором.

Ответ 2

есть другой способ.... очень утомительный... и не совсем транзакции...

Поскольку Firebase позволяет атомизировать изменения в значении, вы можете создать блокировку или семафор со значением "начать транзакцию по ресурсам x, y и z"... конечно, это не настоящая транзакция, поскольку она не блокирует ресурсы, часть из блокировки. Мы могли бы назвать это транзакцией по соглашению. Клиентам необходимо знать, что при блокировке блокировки они не должны изменять ресурсы x, y и z....