Блокировка редактирования элемента, если его кто-то уже редактирует
Есть spa-приложение на blazor. Требуется сделать блокировку элемента для остальных пользователей и уведомление для них, если этот элемент кто-то уже редактирует. На текущий момент есть одна идея:
- Добавить в таблицу сущности столбец LockedUserId(кем заблокирована) и LockedTime(когда). В конфиге проекта хранить время блокировки.
- При загрузке страницы пользователь подписывается на hub(signalr) и конкретно на методы, уведомляющие о блокировке и ее отмене.
- Если пользователь открывает элемент для редактирования, то он вызывает помимо post метода еще и signalr метод о блокировке. Signalr отправляет всем уведомление о блокировке.
- После успешного редактирования/отмены пользователь вызывает или не вызывает нужный api, но в любом случае вызовет signalr метод об отмене блокировки.
- Если пропадает соединение с пользователем или он перезагрузил страницу, то вызывается OnDisconnected signalr метод и заблокированная сущность разблокируется, а также отправится уведомление всем остальным пользователям о снятии блокировки.
Является ли это решение оптимальным?
Ответы (1 шт):
Автор решения: Алексей Якубин
→ Ссылка
Вы пытаетесь придумать механизм для обработки пессимистичных блокировок, сегодня в отрасли есть консенус о том, что подобного дизайна стоит избегать. Поэтому ответ на ваш вопрос - нет, это не оптимально. В вашей ситуации обычно действуют следующим образом:
- Вместо обновления всей сущности через HTTP-метод PUT используют частичное обновление методом PATCH. Таким образом вы сможете значительно уменьшить число ситуаций где блокировка вообще нужна - если у объекта "Адрес" Вася изменил улицу, а Петя номер дома, то они оба правы и мы можем занести это в базу.
- Если таки и Вася и Петя одновременно захотели поменять именно номер дома, то последнему записывающему данные на клиенте просто выводится сообщение о том, что данные уже были изменены и их нужно перечитать. Тут вы уже можете прикрутить какой-то механизм, который автоматически перечитывает, объединяет с изменением пользователя и делает запрос снова, но это уже зависит от вашей задачи (может быть слишком дорого-богато). Например, компания Atlassian в продукте Jira делает обновления задач в трекере по стратегии "побеждает последний", т.е. даже не показывает пользователю, что его изменение конфликтует с другим, а просто тихо перезаписывает. Если Петя сказал, что правильный номер дома теперь 23, то, скажем, если у нас не финансовые транзакции, нам фактически всё равно перезаписывает он 31-й дом или 25-й.