Мне интересно моделировать отношения между документами в CouchDB. Допустим, у меня есть три документа A, B и C. Эти документы могут ссылаться друг на друга, но есть ограничение приложения, что циклическая зависимость не должна возникать.
Давайте рассмотрим пример (-> это маркер зависимости):
A -> B
C
Два клиента (C1, C2) пытаются изменить одновременно:
C1 = B -> C
C2 = C -> A
Если C1 и C2 будут успешными, будет цикл. Вопрос в том, как это предотвратить?
Я думал об этом, и мне кажется, что мне нужна какая-то крупнозернистая блокировка для документов и атомарного массового обновления. Проблема в атомном массовом обновлении. CouchDB поддерживает массовое обновление, но без отката в случае конфликта версий. Что это значит:
Допустим, у нас есть документ V. Этот документ представляет глобальную версию (грубая блокировка) и содержит версию связанных документов (A, B, C) для данной редакции документа.
V {
_rev: 1,
versions: [[A,1],[B,1],[C,1]]
}
С1 и С2 работают одновременно:
C1 = получить V
C2 = получить V
C1 = получить A.1, B.1, C1
C2 = получить A.1, B.1, C1
C1 = сделать проверку зависимостей (все в порядке)
C2 = сделать проверку зависимостей (все в порядке)
C1 = обновить V относительно предполагаемой зависимости B-> C {версии: [[A, 1], [B, 2], [C, 2]]} (все в порядке)
C1 = обновление B
C2 = попытка обновить V в соответствии с предполагаемой зависимостью C-> A {версии: [[A, 2], [B, 1], [C, 2]]}} (этот шаг не будет выполнен из-за CouchDB оптимистическая блокировка)
Все хорошо и хорошо, пока C1 не сломается между шагами 7. и 8. Теперь массовая вставка / обновление поступает на сцену.
7.) C1 = обновить V относительно предполагаемой зависимости B-> C {версии: [[A, 1], [B, 2], [C, 2]]} (все в порядке) и обновить B
Какое прекрасное решение, к сожалению, оно вообще не работает из-за большой семантики вставки / обновления в CouchDB http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API#Transactional_Semantics_with_Bulk_Updates. Массовая вставка / обновление не является атомарной операцией.
Есть ли обходной путь для этого? Могу ли я как-то обойти это? Я пропустил что-то важное?