Я давно использую Syncthing для безсерверной синхронизации файлов между устройствами. Когда-то я перешел с BTSync (позже Resilio) на Syncthing из-за ошибки в мобильном приложении для синхронизации, которая не исправлялась больше полутора лет. Разработчики знали о проблеме, но не спешили выпускать обновление. Resilio — закрытая структура, а Syncthing — это Open Source-система с более чем 300 мейнтейнерами. Вероятнее всего в Resilio просто не было разработчика, способного исправить ошибку. А каждый раз перезагружать приложение мне в результате просто надоело.
С помощью Syncthing я синхронизирую медиафайлы между домашними серверами в разных местах, Obsidian — между всеми устройствами, включая смартфон, а также фотографии и видео из папки DCIM моего Android-смартфона. Я активно использую Syncthing уже довольно долго.
Недавно я столкнулся с небольшой проблемой: некоторые устройства не могут полностью синхронизироваться. Процесс останавливается на 99%, а список несинхронизированных файлов пуст. Это не вызывает особых проблем, так как устройства остаются в постоянном соединении, а «невидимые файлы» не влияют на процесс синхронизации в целом. Однако эту проблему стоит решить, ведь неполная синхронизация — это нехорошо. За постоянной ошибкой могут скрываться незамеченными и действительно серьезные проблемы.
Syncthing создает локальную базу данных, в которой хранятся метаданные о локальных синхронизируемых файлах. Метаданные периодически обновляются, по мере того как изменяются сами файлы. В случае объемных библиотек с файлами, например архива фотографий, построение базы метаданных о файлах может занимать длительное время, поэтому рекомендуется всегда иметь запущенное приложение или сервис Syncthing. Когда метаданные о файлах в синхронизируемой папке актуальны, Syncthing обменивается ими с другими синхронизируемыми устройствами. Именно на основе полученных метаданных от других устройств, Syncthing понимает, какие файлы (или их части) еще не были синхронизированы с другими устройствами.

Пример несинхронизированных устройств через Syncthing с пустым списком файлов, не синхронизированных между устройствами.
Но бывают ситуации, когда одна или несколько синхронизируемых папок обладают метаданными, не отражающими актуальность файлов в папке. А эти метаданные уже сообщены другим устройствам. Устройства ожидают, что эти файлы будут с ними синхронизированы, но не могут произвести синхронизацию, потому что ожидаемые файлы отсутствуют на другом устройстве. Проблема возникает, когда происходит конфликт при синхронизации. Он может возникать по целому ряду причин. Например, два устройства синхронизируются через третье. Не дождавшись полной синхронизации на устройстве № 1, пользователь его выключает, затем переходит на устройство № 2 и там изменяет или удаляет тот файл, который не был полностью синхронизирован с устройства № 1. Ситуация усугубляется, когда синхронизируется большое количество устройств, причем применяется синхронизация не через единый сервер, а сетевым способом (с полной или частичной связанностью), когда устройства могут синхронизироваться не только через какой-то сервер, но и между собой. Собственно, синхронизация без сервера и есть особенность таких систем синхронизации, как Syncthing или того же Resilio. А еще сложнее ситуация становится, когда одно из устройств не имеет права самостоятельно изменять файлы, используется как посредник, либо вообще не является доверенным, а данные на нем хранятся в зашифрованном виде. В такой ситуации ошибки в синхронизации вероятны, особенно если в работу вмешивается человеческий фактор: настраивает версиализацию там, где ее не должно быть, вручную (через интерфейс или файловую систему) отменяет изменения на устройствах-посредниках и тому подобное.
По какой причине возникает ошибка в метаданных — не так уж и важно. Важно, что разработчики осведомлены о проблеме, но не могут ее исправить. А ведь их там 300. Все сводится к тому, что на тестовых системах не удается смоделировать ситуацию, что довольно странно. Но раз уж разработчики не справляются с вопросом, то с ним придется бороться пользователям. Итак, наша задача, во-первых, состоит в том, чтобы выявить проблемную папку, а во-вторых, исправить ситуацию с метаданными.
Шаг 1. Выявление проблемной папки.
Пожалуй, это самый простой шаг. Достаточно войти в интерфейс Syncthing и нажать на паузу на каждой из синхронизируемых папок. Как только синхронизация проблемной папки будет остановлена, так тут же пропадет несинхронизированный статус на устройствах. Не лишним будет добавить, что в целом, к данному действию стоит подходить когда все что нужно уже точно синхронизировано.
Шаг 2. Исправляем ошибку синхронизации.
На этом шаге необходимо разобраться с проблемной папкой и/или с базами метаданных на всех устройствах завязанных в синхронизации этой папки. Звучит страшно, но на деле все не так сложно.
Для начала необходимо перестроить базы метаданных на всех устройствах, которые синхронизируют проблемную папку. Проделать данную операцию через интерфейс можно, в настоящий момент, только в мобильном приложении Syncthing-Fork (оригинальное приложение уже не поддерживается сообществом Syncthing). Но функция перестройки метаданных запрятана глубоко в интерфейсе приложения: системное меню Syncthing-Fork — Настройки — Отладка — Сбросить базу данных. В том же месте располагается и другой пункт «Сбросить изменения индексов», который делает почти то же самое, сбрасывает индексные файлы (используются для ускорения работы базы метаданных). Но надежнее всё же сбрасывать именно саму базу. После сброса базы Syncthing автоматически пересоздаст базу метаданных и ее индексы. Функция пересканирования папок в интерфейсе делает несколько иное. Она нужна, когда необходимо обновить изменения произошедшие в файловой системе и которые не были замечены Syncthing. При пересканировании не происходит полное перестроение базы, вносятся только изменения.
Под операционными системами Linux сброс базы данных придется делать через терминал. Для этого необходимо либо остановить сервис Syncthing через системные процедуры и выполнить команду syncthing --reset-database. А затем запустить сервис заново, и он автоматически произведет пересканирование и пересоздаст базу данных с индексами. Либо поставить на паузу все устройства через интерфейс, выполнить команду syncthing --reset-database, затем выполнить Restart в интерфейсе, что приведет к перезапуску Syncthing и последующим пересканированием файлов, пересозданием базы и индексов.
Под Windows всё немного сложнее. Можно пойти полностью тем же вариантом, как под Linux, но я так и не понял, как остановить сервис Syncthing (он у меня работает не через SyncTraizor или прочие утилиты). Но гораздо проще просто удалить директорию с файлами базы данных. Располагается она обычно в папке \AppData\Local\Syncthing, а называется index-v0.14.0.db. Перед удалением папки нужно убедиться, что удаляется именно она, а не сертификаты шифрования и настройки синхронизации в целом, которые как раз располагаются в папке \AppData\Local\Syncthing. После удаления папки выполнить Restart в интерфейсе Syncthing. Если папка не удаляется, значит, что-то синхронизируется или сканируется. Поставить на паузу все устройства и/или все папки.
Однако далеко не во всех ситуациях операция по обнулению и перестройке базы данных помогает. С чем это может быть связано — не совсем понятно, вероятно, что с конфигурацией файлов для синхронизации и версиализацией. В этом случае необходимо отключить (именно отключить или удалить эту папку в Syncthing, а не поставить ее на паузу) синхронизацию проблемной папки на устройстве. Удалить ее (сделав предварительно копию, на всякий случай) физически с накопителя. Очистить базу данных способом выше. Синхронизировать папку заново с удаленного устройства (устройств).
В конечном итоге всё чинится. Во избежание повторных проблем желательно не использовать версиализацию файлов на недоверенных узлах (где данные хранятся в зашифрованном силами Syncthing виде) и на устройствах-посредниках.

