Можно ли сделать условные вставки с помощью Azure Table Storage - PullRequest
7 голосов
/ 31 января 2012

Можно ли сделать условную вставку с помощью службы хранения таблиц Windows Azure?

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

Если вам интересно, я имею в виду Event Sourcing, но я думаю, что вопрос более общий, чем этот.

По сути, я хотел бы прочитать часть или весь раздел и принять решение на основе содержания данных. Чтобы гарантировать, что ничего не изменилось в разделе с момента загрузки данных, вставка должна вести себя как обычный оптимистичный параллелизм: вставка должна завершиться успешно, только если в разделе ничего не изменилось - строки не были добавлены, обновлены или удалены.

Обычно в REST-сервисе я ожидаю использовать ETag для управления параллелизмом, но, насколько я могу судить, ETag для раздела не существует.

Лучшее решение, которое я могу придумать, - это сохранить одну строку / сущность для каждого раздела в таблице, которая содержит метку времени / ETag, а затем сделать все вставки частью пакета , состоящего из вставки а также условное обновление этой «метки времени». Однако это звучит немного громоздко и хрупко.

Возможно ли это с помощью службы хранения таблиц Azure?

Ответы [ 2 ]

2 голосов
/ 31 января 2012

Как насчет хранения каждого события в «PartitionKey / RowKey», созданного на основе AggregateId / AggregateVersion? Где AggregateVersion - это порядковый номер, основанный на том, сколько событий в агрегате уже есть.

Это очень детерминистически, поэтому при добавлении нового события в агрегат вы убедитесь, что используете его последнюю версию, потому что в противном случае вы получите сообщение о том, что строка для этого раздела уже существует. В настоящее время вы можете отбросить текущую операцию и повторить попытку или попытаться выяснить, можете ли вы объединить операцию в любом случае, если новые обновления в агрегате не конфликтуют с только что выполненной операцией.

2 голосов
/ 31 января 2012

Вид из тысячи футов

Могу ли я поделиться с вами небольшой историей ...Когда-то давно кто-то хотел сохранить события для совокупности (из славы управляемой доменом разработки) в ответ на данную команду.Этот человек хотел убедиться, что агрегат будет создан только один раз и что любая форма оптимистичного параллелизма может быть обнаружена.Для решения первой проблемы - что агрегат должен быть создан только один раз - он сделал вставку в транзакционный носитель, который выбрасывал при обнаружении дублирующего агрегата (или, точнее, его первичного ключа).Он вставил агрегатный идентификатор в качестве первичного ключа и уникальный идентификатор для набора изменений.Коллекция событий, создаваемых агрегатом при обработке команды, - это то, что здесь подразумевается под набором изменений.Если кто-то или что-то еще побеждает его, он рассматривает совокупность, уже созданную, и оставляет это на этом.Набор изменений будет сохранен заранее на носителе по его выбору.Единственное обещание, которое этот носитель должен дать, - вернуть то, что было сохранено как есть, когда его спросят.Любой сбой сохранения набора изменений будет считаться провалом всей операции.Чтобы решить вторую проблему - обнаружение оптимистичного параллелизма в последующем жизненном цикле агрегата - он, после написания еще одного набора изменений, обновит запись агрегата в среде транзакций, если и только если никто не обновил ее за его спиной (то есть по сравнению с тем, что он последний раз читал непосредственно перед выполнением команды).Транзакционная среда уведомит его, если такое случится.Это заставит его перезапустить всю операцию, перечитав агрегат (или его наборы изменений), чтобы на этот раз команда была выполнена успешно.Конечно, теперь он решил проблемы с письмом, вместе с проблемами чтения.Как можно было бы прочитать все наборы изменений агрегата, который составлял его историю?В конце концов, он имел только последний зафиксированный набор изменений, связанный с совокупным идентификатором в этой транзакционной среде.И поэтому он решил вставить некоторые метаданные как часть каждой ревизии.Среди метаданных, которые нередко встречаются как часть набора изменений, был бы идентификатор предыдущего последнего подтвержденного набора изменений.Таким образом, он мог «пройти линию» наборов изменений своего агрегата, как, скажем, связанный список.В качестве дополнительного бонуса он также будет хранить идентификатор командного сообщения как часть метаданных набора изменений.Таким образом, при чтении наборов изменений он мог заранее знать, является ли команда, которую он собирался выполнить в агрегате, уже частью ее истории.Все хорошо, что хорошо кончается ...

PS1. Транзакционный носитель и носитель изменений набора могут быть одинаковыми,2. Идентификатор набора изменений НЕ ДОЛЖЕН быть идентификатором команды,3. Не стесняйтесь пробивать дыры в сказке :-),4. Хотя это не имеет прямого отношения к хранилищу таблиц Azure, я успешно реализовал описанную выше историю, используя AWS DynamoDB и AWS S3.

...