Найти в Дзене
Secret Technologies

Внедрение синхронизации в Secret Cloud Enterprise (SCE)

Давным-давно мы в очередной раз размышляли о том, какой функционал добавить в ещё совсем молодой продукт Secret Cloud (тогда у него ещё даже не было приписки «Enterprise»). У нас было множество вариантов, но остановились мы именно на добавлении синхронизации файлов из облачного хранилища с локальной папкой. И на то были веские причины – постоянные проблемы с подключением по WebDAV. Забегая вперёд, в итоге мы на некоторое время вообще заменили WebDAV функционалом синхронизации и только недавно вернулись к нему с новыми силами, чтобы наконец разрубить этот гордиев узел. Однако на тот момент перед нами стояла достаточно глобальная задача, и не было никакого опыта в её решении. Это сейчас можно открыть диалог с предпочитаемой нейросетью и задать вопрос: «А вот мы хотим внедрить в свой продукт синхронизацию, подскажи, как лучше это сделать?» (статья об использовании нейросетей в работе здесь). Тогда у нас на руках были только смутные идеи и статья на «Хабре» от «Яндекса», в которой описыва
Оглавление

Давным-давно мы в очередной раз размышляли о том, какой функционал добавить в ещё совсем молодой продукт Secret Cloud (тогда у него ещё даже не было приписки «Enterprise»). У нас было множество вариантов, но остановились мы именно на добавлении синхронизации файлов из облачного хранилища с локальной папкой. И на то были веские причины – постоянные проблемы с подключением по WebDAV. Забегая вперёд, в итоге мы на некоторое время вообще заменили WebDAV функционалом синхронизации и только недавно вернулись к нему с новыми силами, чтобы наконец разрубить этот гордиев узел.

Однако на тот момент перед нами стояла достаточно глобальная задача, и не было никакого опыта в её решении. Это сейчас можно открыть диалог с предпочитаемой нейросетью и задать вопрос: «А вот мы хотим внедрить в свой продукт синхронизацию, подскажи, как лучше это сделать?» (статья об использовании нейросетей в работе здесь). Тогда у нас на руках были только смутные идеи и статья на «Хабре» от «Яндекса», в которой описывался процесс внедрения подобного функционала для их «Яндекс.Диска». Довольно интересное ощущение – писать об этом. Как будто передаю эстафету и, возможно, какой-нибудь разработчик в будущем будет читать эти строки и использовать их при реализации подобного функционала в своём продукте.

Первая версия синхронизации, или первый блин – комом

На самом деле, статья на «Хабре» была найдена не сразу, и она послужила больше основой для второй версии реализации, а первая была сделана на базе собственных идей. И сделана она была довольно специфично.

Со стороны сервера особых проблем у нас не было. В Secret Cloud на тот момент уже был реализован функционал уведомлений о результате действия по протоколу WebSocket. Они использовались (и используются по сей день) для вывода уведомлений в интерфейсе. Однако изначально предполагалось, что по информации из них должен был обновляться интерфейс. От этой идеи отказались, но отправку информации об элементе, над которым было выполнено действие, и сам тип действия удалять не стали. И это сыграло нам на руку. По сути, любое действие пользователя, которое он выполняет в интерфейсе Secret Cloud, приходит в единую точку, и остаётся только повторить его в локальной папке.

Проблемы и их преодоление

А вот дальше возникала проблема. Как определить, что пользователь выполнил действие в папке на своём компьютере, и повторить его на сервере? Вторая часть вопросов не вызывала – функционал синхронизации был надстройкой для десктопного клиента, в котором всё общение с сервером было уже реализовано. Оставалось определить действия, выполненные пользователем, и вызвать уже готовый метод.

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

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

Но если бы всё было так просто – не было бы этой статьи. Всплыло ещё несколько моментов, о которых мы, начиная работать над данной задачей, особо не задумывались. Первый из них: вся эта система хорошо работает только в случае, когда приложение запущено постоянно. Любое изменение в локальной папке или через интерфейс вызывает отличия от выстроенной структуры, и система «сходит с ума» в попытках понять, что вообще происходит.

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

Предотвращение конфликтов действий

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

Решилось это довольно просто. Все собираемые действия мы храним в виде списка, который выполняется в отдельном процессе. Мы доработали данный механизм – удаляли выполняемые действия не сразу, а при получении нового выполняли проверку: если это самое действие над этим самым файлом было запрошено приложением с другой стороны (например, новое из локальной папки, а сохранённое с сервера, или наоборот), то именно это и служило триггером для удаления действия из списка, а также для недобавления нового действия.

Особенности работы с офисными файлами

На самом деле была ещё одна сложность при реализации данного функционала, точнее – важный нюанс – офисные приложения. Дело в том, что пока ваш файл открыт в офисном редакторе, внешнее взаимодействие с ним просто невозможно – он полностью заблокирован как для записи, так и для чтения. И нам пришлось что-то с этим делать. Решение было достаточно простым: когда файл открывается в редакторе, рядом с ним всегда создаётся скрытый файл блокировки, повторяющий его имя с добавлением спецсимволов. При закрытии редактора данный файл удаляется. Нам пришлось добавить поддержку файлов блокировки для всех основных офисных редакторов, благодаря чему получилось игнорировать события изменения офисных файлов, а отправку изменений на сервер мы привязали к удалению файла блокировки.

Вот такой вышла наша первая попытка внедрить синхронизацию в Secret Cloud. И да, она не была провальной, как может показаться по описанию выше. Она вполне неплохо работала и полностью выполняла свою задачу. Но оставила ощущение недосказанности для нас самих – хотелось создать более совершенный механизм.

Автор статьи: Захар Максименко, руководитель отдела аналитики компании Secret Technologies.

Хотите узнать больше о возможностях Secret Cloud Enterprise для вашей компании? Свяжитесь с нами для получения консультации или закажите демонстрацию на нашем сайте.

Telegram-канал | Сообщество VK