Допустим, у тебя приложение, которое хранит данные в Markdown-файлах. Простота: открыл файл, отредактировал, сохранил. Никаких миграций — думаешь ты.
Но всё ломается, когда файлы начинают ссылаться друг на друга. Имя файла становится идентификатором. Метаданные содержат инварианты. А изображения привязаны к записям.
Тогда операция «переименовать карточку» — это не просто правка заголовка. Это миграция данных.
Почему просто изменить свойство недостаточно
Возьмём типичный случай: Markdown-заметка со связями. У неё есть имя файла, в front matter указан идентификатор, на неё ссылаются другие заметки, и рядом лежит картинка.
Если поменять только идентификатор в свойствах, имя файла останется старым. Ссылки из других заметок никуда не укажут. Картинка останется с прежним именем, и новые записи не смогут её найти. А дубликаты идентификаторов приведут к неразберихе.
Получается, что «одно маленькое изменение» трогает сразу шесть точек: имя файла, имя изображения, метаданные Cover, ссылки из других файлов, проверки на дубликаты и коллизии, а также старые файлы, которые нужно удалить.
Удаление старой картинки особенно опасно: вдруг на неё ссылается другая заметка.
Итак, переименование — не редактирование поля. Это миграция.
Как выполнить миграцию безопасно
Порядок операций важен. Если что-то пойдёт не так, система не должна оставить ссылки на несуществующий файл. Вот рабочая последовательность:
- Проверяем, что новый идентификатор валиден.
- Отклоняем дубликаты и коллизии имён.
- Переименовываем сам файл в стабильное имя.
- Обновляем все ссылки (обычные и wiki-ссылки) на новое имя.
- Обновляем картинку и метаданные Cover.
- Удаляем старые файлы только после того, как убедились, что они никому не нужны.
- Заново прогоняем аудит коллекции.
Пункт 6 — самый тонкий. Удаление до проверки может уничтожить общий ресурс. Проверка должна быть явной: ищем файл во всех заметках, а не рассчитываем на везение.
Инварианты, которые нужно соблюдать
Локальное хранение не отменяет целостность данных. Ты просто переносишь её из базы в файловую систему. Там инварианты становятся менее очевидными, но не менее важными.
Вот что должно быть неизменно:
- Один стабильный идентификатор у одной карточки.
- Имя файла не должно перезаписывать другой файл.
- Ссылки должны продолжать работать после переименования.
- Общий ресурс нельзя удалять, пока его использует хотя бы одна заметка.
Если хотя бы один инвариант нарушен — система в неконсистентном состоянии. Лучше прервать операцию, чем получить повреждённые данные.
Типичные ошибки и как их избежать
| Ошибка | Последствие | Как избежать |
|---|---|---|
| Поменять только front matter | Несоответствие имени файла и идентификатора, ссылки сломаны | Проверять все связанные поля как единое целое |
| Переименовать файл, не обновив ссылки | Осиротевшие ссылки | Сканировать все заметки на упоминания старого имени |
| Удалить старую картинку сразу | Поломка других заметок, которые её используют | Сначала проверить использование, потом удалять |
| Игнорировать коллизии | Перезапись существующего файла | Запретить именование, если такой файл уже есть |
| Действовать без аудита | Ошибка останется незамеченной | Прогонять аудит до и после операции |
Проверка: нужен не только happy path
Тесты должны покрывать не только успешное переименование, но и отказ. Проверь, что система корректно отклоняет дубликаты, не даёт перезаписать существующий файл, правильно переписывает ссылки. И что повторный аудит даёт стабильный результат.
Только так можно быть уверенным: операция прошла безопасно в любой ситуации.
Правило, которое стоит запомнить
Если изменение значения может сломать ссылки в других местах — проектируй операцию как миграцию.
Файлы — это здорово. Они наглядные, их можно открыть любым редактором. Но как только они начинают выполнять функции базы данных, к ним нужно относиться как к базе данных. С явными правилами, проверками и аудитом.
Комментарии (0)
Войдите, чтобы комментировать.
Пока нет комментариев. Будьте первым.