Изменение описывает три дефекта двусторонней синхронизации: повторную загрузку собственного превью, удаление серверной копии до подтверждения замены и повторную разгрузку только что восстановленного оригинала.
7.4 KiB
Proposal
Why
Режим переноса (C) может залить на сервер превью вместо оригинала и тут же удалить устаревшую серверную копию, то есть молча уничтожить оригинал. Причина — планировщик не отличает содержимое от роли локального файла: когда состояние элемента в локальном индексе расходится с фактической ролью (в индексе «оригинал», на диске превью), смена роли читается как «содержимое изменилось» и запускается цикл «удалил → залил → удалил».
Реальный инцидент: альбом устройства U2, режим переноса, серверный альбом N2. Из 20 фото
пять перезаливались по кругу (20:03 → 20:08 → 20:42 → 21:24), а два потеряли оригиналы —
IMG_20261004_163151.jpg (3 437 694 Б, 3072x4096 → 259 282 Б, 1200x1600) и
IMG_20261009_153136.jpg (2 226 043 Б → 192 651 Б). Лечиться это будет только сейчас:
у первого уцелевший оригинал лежит в корзине сервера, у второго — в корзине и в альбоме
«Первый». Побочно тот же цикл оставляет на телефоне элементы, которых на сервере уже нет:
в приложении альбом N2 показывает 26 плиток вместо 20, шесть из них пустые.
What Changes
- Роль не является содержимым. Приложение SHALL отличать созданное им превью (в том числе по метке провенанса) от нового оригинала: превью никогда не загружается как новая версия и не влечёт удаления серверной копии, а расхождение состояния в индексе выправляется. Настоящее изменение содержимого, как и раньше, синхронизируется новой версией.
- Удаление только после подтверждения. Устаревшая собственная загрузка удаляется только после того, как новая версия подтверждена сервером: сообщённая им контрольная сумма принятого объекта совпала с отправленной. При расхождении загрузка отклоняется вместе с принятой копией, прежняя серверная копия остаётся в альбоме, а замена повторяется при следующей синхронизации. Если сервер контрольную сумму не сообщил (например, старая версия инстанса), загрузка остаётся состоявшейся, но прежняя копия не удаляется.
- Контрольная сумма в ответе на загрузку. Сервер SHALL отдавать контрольную сумму
оригинала в данных созданного фото — как требует существующее требование способности
photos; сегодня ответ на загрузку её не содержит (дефект сервера, а не изменение API). - Разгрузка не гоняется с загрузкой. Оригинал не заменяется превью, пока по этому элементу есть незавершённая загрузка.
- Возврат оригинала устойчив. После возврата оригиналов на устройство элемент не разгружается превью повторно, пока альбом снова не переведён в режим переноса.
- Разовое восстановление двух пострадавших фото из корзины сервера (и альбома «Первый» для второго) с удалением деградировавших копий.
- BREAKING: нет. Успешные сценарии (загрузка нового, разгрузка, повторная синхронизация, настоящее изменение содержимого) сохраняют поведение; меняются только защитные условия.
Capabilities
New Capabilities
Нет — поведение относится к существующей способности синхронизации альбома устройства.
Modified Capabilities
phone-album-sync: различение роли и содержимого (метка превью против нового оригинала), разгрузка только без незавершённой загрузки, удаление устаревшей загрузки только после подтверждения новой версии, устойчивый возврат оригиналов.
Impact
- Код (Android):
data/sync/SyncPlan(различение роли и содержимого, отложенная замена),data/sync/SyncCoordinator(выправление состояния, разгрузка без незавершённых загрузок, постановка замены),data/sync/LocalAssetProvider(метка превью рядом с хешем),data/upload/UploadWorker(сверка принятой контрольной суммы, удаление устаревшей копии после подтверждения, без разгрузки вне координатора),data/sync/RestoreManager(состояние после возврата оригинала),data/db(поле «заменяемое фото» в задании загрузки). - Схема Room: версия 8 → 9,
ALTER TABLE upload_jobs ADD COLUMN replacesPhotoId TEXT. - API и бэкенд: не затрагиваются — используются существующие
DELETE /api/photos/{id}(мягко, в корзину),POST /api/photos/{id}/restoreиoriginal_checksumв ответе загрузки. - Данные инстанса: разовое восстановление двух оригиналов и удаление деградировавших копий (операция, а не постоянное поведение).
- Не затрагивается: серверная модель версий/идентичности, дедупликация вложения, чистка кэша альбома на телефоне (пустые плитки удалённых фото — отдельная задача), доверие к метаданным MediaStore при кэшировании хешей (сверка контрольной суммы закрывает риск).