Как сделать совместное редактирование данных на сайте?
Привет всем!
Есть многопользовательский сайт, написанный на React + бэкенд + MySQL.
Для простоты пусть это будет тривиальный TODO-app.
Пользователи одновременно могут редактировать данные:
добавлять и удалять TODO; редактировать название/описание и другие поля.
Задача: Придумать логику работы.
Какие вижу сложности:
— У пользователя в любой момент может пропасть интернет. Не хочется сразу запрещать возможность редактирования. Хочется дать возможность работать в оффлайне, и синхронизировать данные при подключении.
— При повторном подключении необходимо отправлять все изменения на сервер. Но как быть с конфликтующими изменениями, произошедшими пока не было интернета? Имею ввиду, что 2 пользователя редактировали один и тот же TODO в оффлайне, а затем подключились и нужно синхронизировать изменения.
— Здесь также появляется проблема выстраивания изменений в хронологическом порядке. Ведь нужно чтобы они шли в хронологическом порядке. Соответственно, они должны иметь какую-то метку времени. Но на клиенте может быть установлена неверная дата. И вообще она может измениться в любой момент. Можно делать какую-то синхронизацию с сервером, но тут тоже много сложностей.
— В конце концов, есть проблема слияния данных нескольких TODO. В первую очередь, речь конечно же о текстовых полях. Например, если 2 пользователя одновременно редактируют название.
— А ещё это всё нужно сохранять в базе. И как быть с ситуацией, когда на сервер дошли какие-то более старые изменения чем те, которые уже сохранены в базе?
В общем, хотелось бы узнать кто как решал подобные проблемы?
Может есть какие-то готовые решения для описанных задач?
У каждого действия должен быть timestamp, когда появляется интернет всё пушится на сервак, а там по времени решается
А как быть с ситуацией, когда например пользователь А что-то отредактировал в оффлайн-режиме, а пользователь Б - в онлайн. Соответственно изменения пользователя Б применились сразу. А затем пришли изменения пользователя А. Они как бы уже получаются устаревшие...
в конфликтах побеждает последний по timestamp
Тут тоже свои сложности. Во-первых, нужно как-то время клиентов синхронизировать, а во-вторых тут могут быть гораздо более сложные ситуации. Например, пользователь А удалил TODO, а через миллисекунду пришли данные о том, что пользователь Б отредактировал описание этого TODO.
У меня была немного другая задача, но очень близкая, от реализации которой я в итоге отказался, но в процессе изучения как можно это решить, узнал про https://en.wikipedia.org/wiki/Conflict-free_replic...
Такие структуры позволяют менять общие данные независимо и параллельно и затем их объединять в результат.
Возможно это вам подскажет нужное направление мысли.
в качестве бонуса - возможно что для вас данные - это не текст и тудушки, а пользовательские действия. С большой вероятностью в таком виде вам будет проще объединять и синхронизировать.
Robur, интересная статья. Спасибо!
Честно говоря, я не придумал как применить эту информацию в моей ситуации, но всё равно какие-то новые мысли появились.
возможно что для вас данные - это не текст и тудушки, а пользовательские действия. С большой вероятностью в таком виде вам будет проще объединять и синхронизировать.
Да, разумеется. Я же как раз и описал в вопросе подход, когда пользователи отправляют на сервер лишь свои действия (то есть внесённые изменения). И описал связанные с этим подходом проблемы, которые нужно решить.
Или вы предлагаете в базе хранить тудушки тоже в виде пользовательских действий (или патчей), а не полноценных сущностей? Прям как Гит, или h264 :)
В таком случае действительно, некоторые проблемы, связанные со слиянием, будут нивелированы. Но какой будет оверхед на вычисления - сложно представить. Надо подумать.