Введение
Начиная с версии Discourse 3.2.0.beta3, темы и компоненты Discourse могут использовать функцию миграций для бесшовной эволюции и изменения своих настроек. Эта функция гарантирует, что обновления тем не нарушат работу существующих установок, так как изменения настроек обрабатываются контролируемым образом.
Когда использовать миграции
Типичные сценарии, где миграции особенно полезны:
- Изменение типа настройки (например, с строки с разделителями-запятыми на список).
- Переименование настройки.
- Изменение структуры или формата данных, хранящихся в настройке.
В этих сценариях, если тип или имя настройки изменены в файле settings.yml без соответствующей миграции, существующие установки, где настройка была изменена пользователем относительно значения по умолчанию, потеряют эти изменения и могут привести к сбоям при обновлении темы.
Чтобы обеспечить плавный переход при обновлении настройки темы, разработчики тем должны поставлять миграцию, которая инструктирует ядро Discourse о том, как перенести существующее состояние, соответствующее старой версии settings.yml, в новую версию.
Файлы миграций
Миграции — это файлы JavaScript, расположенные в директории migrations/settings темы, следуя соглашению об именовании XXXX-имя-миграции.js. Префикс XXXX — это номер версии, начинающийся с 0001 и последовательно увеличивающийся, который определяет порядок выполнения.
Имя должно быть кратким описанием цели миграции, состоящим только из алфавитно-цифровых символов и тире, и не превышать 150 символов в длину. Миграции выполняются в возрастающем порядке на основе числового значения их версий.
Рекомендуется начинать с 0001 для первой миграции, 0002 для второй и так далее. Обратите внимание, что если версия миграции меньше 1000, то она должна быть дополнена ведущими нулями до длины в 4 цифры, так как имя файла миграции должно начинаться с 4 цифр. По той же причине в текущий момент невозможно иметь более 9999 миграций в теме, хотя в будущем это ограничение может быть изменено.
Функция миграции
Стандартные возможности JavaScript функции, такие как классы, функции, массивы, карты и т.д., доступны для использования в миграциях. Единственное требование от ядра Discourse заключается в том, что каждый файл миграции должен экспортировать функцию по умолчанию, которая служит точкой входа. Эта функция принимает объект Map, представляющий измененные настройки темы, и возвращает объект Map, отражающий желаемое конечное состояние всех настроек.
Примеры
Переименование настройки темы:
// filename: 0001-rename-old-setting.js
export default function migrate(settings) {
if (settings.has("old_setting_name")) {
settings.set("new_setting_name", settings.get("old_setting_name"));
settings.delete("old_setting_name");
}
return settings;
}
Эта миграция должна сопровождаться переименованием настройки в файле settings.yml.
Преобразование строковой настройки с разделителями-запятыми в правильный список:
// filename: 0001-convert-string-setting-to-list.js
export default function migrate(settings) {
if (settings.has("list_setting")) {
const list = settings.get("list_setting").split(",");
settings.set("list_setting", list.join("|"));
}
return settings;
}
Аналогично предыдущему примеру, эта миграция должна сопровождаться изменением типа настройки с string на list в файле settings.yml.
Переименование варианта в настройке типа enum:
// filename: 0001-rename-enum-choice.js
export default function migrate(settings) {
if (settings.get("enum_setting") === "old_option") {
settings.set("enum_setting", "new_option");
}
return settings;
}
Добавление нового элемента в настройку списка:
// filename: 0001-add-item-to-list.js
export default function migrate(settings) {
if (settings.has("list_setting")) {
const list = settings.get("list_setting").split("|");
list.push("new_item");
settings.set("list_setting", list.join("|"));
} else {
settings.set("list_setting", "new_item");
}
return settings;
}
Выполнение и обработка ошибок
Миграции выполняются автоматически при установке темы и её обновлении. Они выполняются только один раз; если миграция изменена после успешного выполнения, она не будет запущена снова. Если миграция завершается ошибкой, процесс обновления останавливается, и отображается сообщение об ошибке с описанием проблемы.
Если в миграции есть ошибка, приводящая к повреждению состояния настройки, правильным способом исправления проблемы является создание новой миграции, которая исправляет поврежденное состояние, а не изменение исходной миграции.
Этот документ находится под контролем версий — предложите изменения на GitHub.