Я работаю над чем-то похожим на pastebin (да, это это универсально), но допускает редактирование несколькими пользователями. Очевидная проблема заключается в том, что несколько пользователей пытаются редактировать один и тот же файл. Я думаю о том, как заблокировать файл, когда над ним работает один пользователь (это не лучшее решение, но мне не нужно ничего слишком сложного), но для предотвращения / предупреждения пользователя мне, очевидно, понадобится система контроля за сессиями редактирования каждого пользователя. Работая с базой данных и ajax, я думаю о двух решениях.

Первым было бы, чтобы страница редактирования пинговала сервер с произвольным интервалом, скажем, в минуту, и это обновило бы запись сеанса редактирования в БД. Затем в следующий раз, когда запрос скрипта на редактирование, он проверяет самый последний пинг, и, если самым последним был другой произвольный период времени, скажем, пять минут, то мы предполагаем, что предыдущий пользователь завершил работу, и файл можно снова отредактировать. Конечно, проблема с этим методом состоит в том, что предположение о том, что предыдущий пользователь вышел, является просто предположением. У него могло быть слабое соединение Wi-Fi, и он просто выпадал на десять минут, все время с открытым окном.

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

Итак, я пришел, чтобы придумать другое решение. Также возможно получить событие unload для запуска, когда сеанс пользователя завершится, но я не уверен, будет ли это работать надежно.

Есть ли у кого-нибудь другое, более изящное решение этой проблемы?

5
Yi Jiang 20 Авг 2010 в 14:51

4 ответа

Лучший ответ

Если вы ожидаете, что количество одновременных правок файла будет незначительным, вы можете просто сохранить номер версии файла в БД, и когда пользователь загружает файл в свой браузер, он также получает номер версии. Они могут загружать свои изменения только в том случае, если номер версии совпадает. Первый загрузит выигрыш. При обнаружении конфликта вы должны отправить обратно самый последний файл и изменения пользователя, чтобы пользователь мог вручную внести изменения. Преимущество в том, что это работает, даже если один и тот же пользователь делает два одновременных редактирования. Если эта функция часто используется, вы можете добавить слияние на стороне клиента, аналогичное тому, которое использует инструмент сравнения (но в этом случае вам может понадобиться сохранить старые ревизии).

6
Mr. Shiny and New 安宇 31 Авг 2010 в 15:18

Я бы сказал, что вы на правильном пути. Я бы, вероятно, реализовал гибридное решение:

Имейте одну таблицу с именем "active_edits" или что-то подобное со столбцом для document_id, пользователя и last_update_time. Допустим, ваше время пинга составляет 1 минуту, а время ожидания - 5 минут. Таким образом, вариант использования будет выглядеть так:

Боб открывает документ. Проверяет last_update_time. Если это более 5 минут назад, обновите таблицу с Бобом и текущим временем. Если это не так, над документом работает кто-то другой, поэтому выведите сообщение об ошибке. Предполагая, что он не редактируется, Боб некоторое время работает над документом, и клиент пингует время обновления каждую минуту.

Я бы сказал, что do включает кнопку «Закончить редактирование» и обработчик onunload. Насколько я понимаю, может быть ненадежным, но может также добавить его. Оба из них будут отправлять на сервер одно сообщение только для отправки о том, что Боб готов. Даже если Боб не нажмет «Закончить редактирование» и выгрузится из-под загрузки, в худшем случае другому пользователю придется подождать еще 5 минут для редактирования. Преимущество состоит в том, что если они обычно работают (справедливое предположение), то система работает немного лучше.

В случае, когда вы описали, где у Боба плохое беспроводное соединение или он делает перерыв: я бы сказал, что это не имеет большого значения. Ваша функция ping должна убедиться, что документ не был передан кому-либо еще со времени последнего пинга Боба. Если это так, просто дайте Бобу сообщение «кто-то еще начал работать над документом» и дайте им возможность перезагрузить.

РЕДАКТИРОВАТЬ: Кроме того, я хотел бы изучить window.onbeforeunload, а не onunload. Я считаю, что это выполняется раньше. Я полагаю, что это функция веб-сайта (включая slashdot), позволяющая вам подтвердить, что вы действительно хотите покинуть страницу. Я думаю, что это работает в основных браузерах, кроме Opera.

0
InvisibleBacon 27 Авг 2010 в 15:35

Как и с этим вопросом SO Как вы управляете одновременным доступом к формы? я бы не стал пытаться реализовать пессимистическую блокировку. Просто слишком сложно надежно работать в среде без гражданства. Вместо этого я бы использовал оптимистическую блокировку. Однако в этом случае я использовал что-то вроде хэша файла SHA, чтобы определить, изменился ли файл с момента последнего чтения файла пользователем. Для каждого запроса на изменение файла вы запускаете хэш SHA байтов файла и сравниваете его с версией, которую вы указали при первом чтении данных. Если оно изменилось, вы отклоняете это изменение и либо заставляете пользователя снова вносить свои изменения (извлекая новую копию содержимого файла), либо вы предоставляете более подходящее разрешение конфликтов.

0
Community 23 Май 2017 в 12:06

Вам, вероятно, лучше пойти на решение "слияния". Используя этот подход, вам нужно проверять изменения только тогда, когда пользователь публикует свой документ на сервере.

Основной подход будет следующим: 1. Пользователь A получает документ для редактирования, документ имеет версию 1 2. Пользователь B получает документ для редактирования, документ имеет версию 1 3. Пользователь B публикует некоторые изменения, включая номер базовой версии 1 4. Сервер обновляет документ, документ теперь версии 2. 5. Пользователь B публикует некоторые изменения, в том числе номер базовой версии 1 6. Сервер отвечает, что документ изменился с момента, когда пользователь начинает редактирование, и отправляет пользователю новый документ и его версия - пользователю затем необходимо выполнить любое объединение своих изменений в документ версии 2 и отправить обратно на сервер. По сути, пользователь сейчас редактирует документ версии 2 7. Пользователь A публикует некоторые изменения, включая номер версии 2 8. Сервер обновляет документ, который теперь имеет версию 3

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

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

2
David_001 22 Авг 2010 в 15:06