Перейти к содержимому

Устаревание и апгрейды

Блок живёт дольше страницы, на которую его поставили. Эта страница — про то, как выглядит его старение с обеих сторон: для автора блока и для владельца страниц, на которых блок стоит.

У глобального блока есть флаг «устаревший» (is_deprecated). Он не удаляет блок, а убирает его с витрины:

  • блок пропадает из списка блоков и из поиска;
  • уже добавленные экземпляры продолжают работать и публиковаться как прежде;
  • администратор видит такие блоки с явной пометкой «Устаревший».

Флаг ставит администратор и только глобальному блоку. Свой приватный блок пометить устаревшим нельзя — его достаточно удалить или перестать использовать.

Что делать, если нужный вам блок устарел:

  1. Посмотреть, нет ли в каталоге блока на замену.
  2. Форкнуть устаревший блок, пока он ещё доступен, — форк станет вашим приватным блоком и от чужих решений больше не зависит.
  3. Перевести страницы на замену — это ручная миграция, см. ниже.

Экземпляр блока закреплён за ревизией, с которой его добавили (почему). Обновление — явное действие, и вариантов ровно два.

Если у библиотечного блока выросла только минорная часть версии (1.21.5), экземпляр переводится на свежую ревизию без потери значений:

POST /api/v1/pages/{pageId}/blocks/{pbId}/upgrade

Экземпляру проставляется новая ревизия, версия и свежий снимок схемы; placeholder_values остаются как были. Поля, которые появились в новой версии, берут значения по умолчанию.

Всю страницу разом обновляет:

POST /api/v1/pages/{pageId}/blocks/upgrade-all

Ответ разложен на три группы:

Поле ответа Что там
upgraded обновлённые экземпляры с версиями «из» и «в»
skipped_major пропущенные из-за ломающего изменения, с removed_fields
already_up_to_date те, кому обновление не требовалось

Операция атомарная: либо применились все minor-обновления, либо ни одно.

Если у блока сменилась мажорная версия, автоматический апгрейд не выполняется — из схемы исчезли поля, и молча перенести значения некуда. Запрос вернёт 422:

{
"error": "major_upgrade_blocked",
"message": "Block has breaking changes (v1.2 → v2.0). Migrate manually…",
"current_pin": { "major": 1, "minor": 2 },
"library_version": { "major": 2, "minor": 0 },
"removed_fields": ["subtitle", "cta"]
}

removed_fields — это и есть план миграции: список того, чему в новой схеме нет соответствия.

Порядок действий:

  1. Прочитать новую схему блока — GET /api/v1/blocks/{id}/placeholder-schema даёт готовый контракт значений и минимальный валидный пример.
  2. Сопоставить старые значения с новыми полями. Для полей из removed_fields решить, куда переносится содержимое (или что оно больше не нужно).
  3. Заменить экземпляр на странице, передав новые значения:
PUT /api/v1/pages/{pageId}/blocks/{pbId}/replace
{ "block_id": 7, "placeholder_values": { … } }

Замена сохраняет позицию блока на странице: старый экземпляр удаляется, новый встаёт на его место и закрепляется за актуальной ревизией.

Эквивалентный путь — вставить новый экземпляр на ту же позицию (POST /api/v1/pages/{pageId}/blocks) и удалить старый (DELETE /api/v1/pages/{pageId}/blocks/{pbId}). Разница только в количестве запросов.

Аудит удобно делать в два шага:

  1. Найти страницы с неактуальными блоками: GET /api/v1/pages?has_outdated=1.
  2. Для каждой вызвать upgrade-all и разобрать skipped_major — это очередь ручной работы.

Так автоматическая часть закрывается одним проходом, а внимание тратится только на действительно ломающие изменения.

  • Ломающее изменение стоит дорого: после major никто не обновится автоматически. Каждый пользователь блока будет мигрировать руками.
  • Хотите убрать поле — сначала перестаньте использовать его в шаблоне, оставив в схеме. Удалить его можно будет позже, когда это перестанет кого-либо касаться.
  • Меняете смысл поля при том же имени — это minor, автоматика ничего не заподозрит. Пишите об этом в changelog явно.
  • Блок стал не нужен — не удаляйте глобальный блок, а попросите пометить его устаревшим: страницы пользователей останутся живыми.

Источники: backend/src/Entity/Block.php (isDeprecated), backend/src/Service/Block/UpdateBlockService.php, backend/src/Repository/BlockRepository.php, backend/src/Service/Page/{UpgradePageBlockService,BulkUpgradePageBlocksService,ReplacePageBlockService}.php, backend/src/Controller/V1/PageBlock/**, backend/src/Service/BlockVersionService.php (computeUpdateStatus, detectRemovedFields).