Архитектура для редактирования иерархии с несколькими уровнями узлов с несколькими пользователями

Я создаю модуль для редактирования иерархии узлов. Вы можете думать об этом как об очень большой структуре каталогов со многими уровнями вложенных каталогов и файлов. Узлы иерархии хранятся в таблице реляционной базы данных. Единственная разница в том, что нет такой вещи, как папка/каталог. Все узлы имеют одинаковые характеристики. Таким образом, у узла есть родитель, который также является узлом. И есть только один корневой узел, и у узла может быть только один родительский узел, так что полииерархий нет.

Столбцы таблицы:

node_id [bigint] not null
name [nvarchar(50)]
parent_node_id [bigint]
leaf_node [bit]

Цель состоит в том, чтобы найти способ редактировать одну иерархию, чтобы пользователи не наступали друг другу на пятки. Мы либо должны разработать архитектуру контроля версий для разрешения конфликтов, либо использовать какой-либо механизм блокировки (пессимистичный или оптимистичный), чтобы другие не могли редактировать узлы, которые являются частью предка (или поддерева) некоторого заданного родительского узла во всей иерархии. дерево. Если мы будем выполнять блокировки, то всем, кто использует редактор, нужно будет постоянно обновлять свое дерево, чтобы видеть изменения других.

Есть только три особенности, о которых стоит беспокоиться. Редактирование узла/объекта в мастер-дереве разрешено только одному пользователю. Перетаскивание вновь созданного поддерева в главное дерево. Перетаскивание поддерева в главном дереве в другой узел в главном дереве, что делает отброшенное поддерево дочерним элементом этого узла.

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

Вот мой план на данный момент:

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

  • если новое поддерево перетаскивается в родительский узел главного дерева, заблокируйте новый родитель. Затем вставьте новые записи и обновите корневой родительский элемент, чтобы он указывал на родительский узел основного дерева. Затем уведомите всех клиентов, чтобы они обновили свое основное дерево. Таким образом, вся блокировка происходит на стороне базы данных после того, как произойдет удаление.

  • если существующий родительский узел главного дерева перетаскивается в существующий родительский узел главного дерева и становится дочерним узлом, то мы должны заблокировать старый родитель (становясь новым дочерним элементом) и заблокировать нового родителя. Затем обновите родительский узел нового дочернего элемента. Затем обновите всех клиентов (всех пользователей) и обновите их основное дерево. Таким образом, вся блокировка происходит на стороне базы данных после того, как произойдет удаление.


person MacGyver    schedule 19.01.2013    source источник


Ответы (1)


Для 1 вы можете использовать просто оптимистическую блокировку. (Ваш текущий подход подразумевает, что «последние данные перезаписывают существующие»).

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

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

person mikalai    schedule 21.01.2013
comment
когда вы говорите блокировку ссылки, вы подразумеваете, что дочерний элемент указывает на родителя, а родительский элемент указывает на дочерний элемент? Как бы вы порекомендовали обрабатывать обновления клиента? - person MacGyver; 11.02.2013
comment
Нет. Это не ссылка, соединяющая узлы. Это прежде всего блокировка, а это означает, что вы явно управляете пессимистическими блокировками. Поэтому перед выполнением операции ссылки вы создаете блокировку ссылки (блокируете оба конца от повторной ссылки). Если какой-то из концов уже залочен - откат транзакции. Также я не уверен, как эта блокировка будет работать для конечного пользователя. По сути, мы намеренно выполняем блокировку перед тем, как пользователь внесет изменения (например, откроет окно редактирования). Но как такую ​​блокировку можно применить для операций перетаскивания? Вы начинаете перетаскивать и точно знаете один узел, но как узнать пункт назначения? - person mikalai; 01.03.2013