Гарантия согласованности в FaunaDB при перезаписи документа, который был прочитан в прошлом
У меня есть FaunaDB, с которой я хотел бы взаимодействовать как хранилище документов. У меня есть один API, который:
- Читает весь документ из FaunaDB
- Изменяет эти данные произвольно на основе ввода в API
- Пишет мутировал обратно, гарантируя, что данные не были мутированы
- Ошибка или повтор, если чтение не было текущим при попытке записи
В Postgres для обеспечения согласованности я бы просто использовал предложение where. Поскольку фауна распространяется, я предполагаю, что эквивалент более нюансирован, например, насколько я понимаю, записи CosmosDB идиоматически отправляют eTag чтения для проверки, чтобы гарантировать согласованность.
1 ответ
В фауне все транзакции записи проходят через конвейер транзакций в строгой сериализуемой изоляции. Таким образом, все, что нам нужно для поддержания желаемого инварианта двух наших транзакций, - это убедиться, что мы связываем нашу запись с чтением, которое проверяет, что документ не обновлялся, пока мы копались в нашем собственном коде. Позволять $ref
быть какой-то ссылкой, что у нас есть магические знания. Позволять $ts
быть результатом Select("ts", Get($ref))
во время нашей первоначальной транзакции чтения. Позволять $expr
быть тем, чем мы хотим обновить наш документ. Затем:
If(Equals(Select("ts", Get($ref)), $ts), Update($ref, $expr), Abort("try again"))
Конечно, вы, вероятно, хотите сделать что-то умнее: возможно, лучше не возвращать обновленный документ. Как именно вы хотите структурировать это зависит от вас, но
{error: "ts out of date", updated: Get($ref)}
Работало бы достаточно хорошо, вам просто нужно было бы провести анализ полученного объекта, чтобы определить, есть ли у вас документ или произошел сбой. Вы даже можете получить все фантазии и переместить экземпляр в Let
но характеристики времени выполнения практически одинаковы (чтение кэшируется локально во время eval, мы не будем делать это дважды).