- PVSM.RU - https://www.pvsm.ru -
У Dropbox есть три API для мобильных приложений:
Sync API хорош, но по статистике, многие мобильные разработчики используют его для хранения структурированных данных. Сериализуют их в JSON, сохраняют в файлы, синхронизируют с облаком. Это работает до тех пор, пока не происходит одновременного изменения данных с разных устройств. Даже если вы поменяете не конфликтующие по смыслу данные, на уровне файла это будет конфликт и Dropbox не сможет его решить.
Поэтому мы выпустили Datastore API [4]. Он синхронизируем не файлы, а данные, чем-то похож на удаленную NoSQL базу данных с кешированием.
Например, у вас есть SQLite база данных. Она синхронизируется с облаком при помощи Dropbox Core API. Если поменять значения в разных строках таблицы на разных устройствах, мы получим конфликт синхронизации файла. Хотя изменения на уровне данных не конфликтуют с друг другом. Datastore API решает эту проблему.
В DataStore используется не реляционная модель данных, а что-то похожее на NoSQL. У каждого Dropbox пользователя есть хранилище, хранилище содержит в себе таблицы. Таблицы делятся на записи у каждой записи есть поля со значениями. Записи в таблице могут иметь разный набор полей, то есть фактически это не таблица, нет строк и столбцов, нет жесткой структуры.
Магия начинается после вызова метода sync. В iOS и Android sync вызывается после завершения осмысленной последовательности изменения данных. Можно сравнить с коммитом в системах контроля версий.
В фоне Dropbox постоянно получает изменения данных с сервера. Когда вы вызываете sync ваши локальные изменения объединяются с правками на сервере и посылаются обратно. Серверные изменения применяются к локальной копии только после вызова Sync.
Мы уделили много внимания разрешению конфликтов. Конфликт происходит когда два устройства одновременно обновляют одно и то же хранилище. Например, два устройства теряют доступ к интернету. Локально сохранена ревизия 1 хранилища. Оба устройства меняют данные в хранилище. При появлении интернета и синхронизации устройств с сервером мы получим две разные версии ревизии 2, это и есть конфликт.
Если изменения в конфликтной ревизии затрагивали разные записи они объединяются автоматически. Если изменения коснулись одной и той же записи, применяются правила разрешения конфликтов. Правила устанавливаются на уровне таблиц или полей.
При применении этих правил сервером вы получите ошибку синхронизации с подробностями об изменениях и можете программно объединить данные и послать их на сервер еще раз.
По умолчанию работает правило «выигрывает сервер». Если приложение пытается отправить изменение поля на сервер, которое уже было изменено, остается версия сервера, значение поля пришедшее с устройства выбрасывается. Например, у меня нет доступа к сети и я на своем смартфоне меняю номер телефона Маши на 911. Тем временем моя секретарша, с доступом к интернету, меняет номер Маши на 112. Когда мой смартфон выйдет в онлайн, мои изменения номера будут отброшены. Номером Маши будет 112.
Можно поменять правило по умолчанию на «выигрывает клиент», все изменения сервера будут отброшены и номером Маши будет 911. Что достаточно странно, поэтому «выигрывает сервер» правило по умолчанию.
Для числовых значений дополнительно есть правила «минимума», «максимума» и «суммы». То есть в конфликтной ситуации будет выбрано минимальное или максимальное значение. «Максимум» удобен для значений которые не должны уменьшаться, например инкрементальных счетчиков.
В правиле «суммы» результатом разрешения конфликта будет сумма изменений значения. Звучит странно, но работает, например, для счетчика нажатий на кнопку в приложении. Пользователь одновременно нажимает ее с двух разных устройств, сервер суммирует результат. Два устройства синхронизируются с сервером, в поле было 3. Одно устройство поменяло его на 4, другое на 5. Результатом синхронизации поля будет 6.
Для разрешения конфликтов в списках мы используем Операциональное преобразование [5] (Operational Transformation). Оно так же используется в Google Wave и Google Docs.
Например, у нас есть список ACZ. На одном устройстве вставляем B на вторую позицию и одновременно вставляем Z с другого устройства на третью. Результат должен быть ABCXZ, а не ABXCZ. Звучит просто, но реализация потребовала применения хитрых алгоритмов.
Проектированием хранилища и разрешением конфликтов занимается Гвидо Ван Россум (создатель языка Python, сейчас работает в Dropbox). Он написал подробный технический пост [6] о том как это происходит.
Официальный компонент Dropbox API [7] есть в магазине компонентов Xamarin.
Подробный шаг-за-шагом пример разработки приложения с Datastore API в блоге Xamarin [8].
прим. пер. По-моему, новый API от дропбокса очень кстати. При разработке Coin Keeper [9] мы очень много времени потратили на придумывание и реализацию синхронизации приложения с сервером. Потом еще два месяца исправляли ошибки. С Datastore API все было бы гораздо проще. С другой стороны, все достоинства перечеркиваются требованием Dropbox-аккаунта от пользователя.
А вы бы стали использовать Datastore API в своем приложении?
Автор: junk
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/dropbox/44894
Ссылки в тексте:
[1] Drop-ins: https://www.dropbox.com/developers/dropins
[2] Core API: https://www.dropbox.com/developers/core
[3] Sync API: https://www.dropbox.com/developers/sync
[4] Datastore API: https://www.dropbox.com/developers/datastore
[5] Операциональное преобразование: http://ru.wikipedia.org/wiki/%D0%9E%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5
[6] подробный технический пост: https://www.dropbox.com/developers/blog/48/how-the-datastore-api-handles-conflicts-part-1-basics-of-offline-conflict-handling
[7] компонент Dropbox API: http://components.xamarin.com/view/dropboxsync/
[8] блоге Xamarin: http://blog.xamarin.com/a-quick-look-at-dropbox%E2%80%99s-new-datastore-api%E2%80%A6-in-c-sharp/
[9] Coin Keeper: http://touchin.ru/portfolio/coinkeeper/?utm_campaign=79
[10] хабра-блог: http://habrahabr.ru/company/touchinstinct/
[11] Источник: http://habrahabr.ru/post/196208/
Нажмите здесь для печати.