Система миграций плагинов позволяет плагинам автоматически обновлять схему базы данных и данные при обновлении до более новых версий. Эта система работает аналогично основной системе миграций, но специфична для отдельных плагинов.
Как это работает
- Автоматическое обнаружение: При загрузке плагина система автоматически проверяет наличие ожидающих миграций
- Отслеживание версий: Версия каждого плагина отслеживается отдельно в базе данных
- Файлы миграций: Миграции хранятся в директории migrations/ внутри каждого плагина
- Автоматическое выполнение: Миграции автоматически применяются при увеличении версии плагина
- Начальные данные сначала: Настройки и метаобъекты создаются из initial_data.py перед запуском миграций
- Только изменения данных: Миграции должны фокусироваться на изменении данных, а не на создании элементов схемы
- Интеграция с сервисами: PluginMigrationService доступен через services.plugin_migrations как и другие сервисы
Структура файлов
plugins/
├── your_plugin/
│ ├── info.json # Содержит версию плагина
│ ├── plugin.py # Основной файл плагина
│ ├── migrations/ # Директория файлов миграций
│ │ ├── __init__.py
│ │ ├── template.py # Шаблон для новых миграций
│ │ ├── 1_0_1.py # Миграция для версии 1.0.1
│ │ ├── 1_0_2.py # Миграция для версии 1.0.2
│ │ └── 2_0_0.py # Миграция для версии 2.0.0
│ └── ...
Формат файла миграции
Файлы миграций должны называться с использованием номера версии, где точки заменены подчеркиваниями:
- Версия 1.0.1 → имя файла 1_0_1.py
- Версия 2.1.0 → имя файла 2_1_0.py
Каждый файл миграции должен содержать функцию up():
def up():
"""
Код для обновления базы данных плагина до этой версии
"""
from core.data import storage
# Пример: Обновление существующего значения настройки
storage.settings.set('your_plugin_setting', 'new_value')
Создание миграций
Ручное создание
- Создайте директорию migrations/ в вашем плагине, если она не существует
- Скопируйте шаблон из plugins/example_plugin/migrations/template.py
- Переименуйте его в вашу версию (например, 1_0_1.py)
- Реализуйте функцию up() с вашей логикой миграции
Начальные данные vs Миграции
Начальные данные (initial_data.py)
- Назначение: Определение схемы и структуры
- Когда выполняется: Каждый раз при загрузке плагина
- Что помещать сюда:
- Определения настроек (структура, а не значения)
- Сигнатуры метаобъектов
- Группы настроек
- Данные по умолчанию, которые должны всегда существовать
Миграции
- Назначение: Изменение данных и значений при обновлении версий
- Когда выполняется: Только при обновлении до новой версии
- Что помещать сюда:
- Обновление значений настроек
- Добавление/удаление записей
- Преобразования данных
- Изменения схемы, которые нужно применить один раз
Пример рабочего процесса
- Версия 1.0.0: Определите настройки в initial_data.py
- Версия 1.0.1: Используйте миграцию для обновления значений настроек
- Версия 1.1.0: Добавьте новые настройки в initial_data.py, используйте миграцию для установки их значений
Примеры миграций
Обновление значения настройки
def up():
from core.data import storage
# Обновление существующей настройки на новое значение
storage.settings.set('my_plugin_api_key', 'new_api_key_value')
Добавление данных в метаобъекты
def up():
from core.data import storage
# Добавление данных по умолчанию в метаобъект (определенный в initial_data.py)
storage.metaobjects.create('my_plugin_items', {
'name': 'Default Item',
'description': 'Created by migration'
})
Обновление существующих записей
def up():
from core.data import storage
# Обновление существующих записей для добавления нового поля
existing_records = storage.metaobjects.get_metaobject_data('my_plugin_items')
for record in existing_records:
if 'old_field' in record:
storage.metaobjects.update('my_plugin_items', record['_id'], {
'new_field': record['old_field'],
'$unset': {'old_field': 1}
})
Лучшие практики
- Тестируйте миграции перед развертыванием в продакшене
- Используйте описательные имена миграций, которые объясняют, что делает миграция
- Держите миграции маленькими и сфокусированными — одно логическое изменение на миграцию
- Обновляйте версию плагина в info.json при добавлении миграций
- Документируйте ваши миграции с четкими комментариями
- Не создавайте настройки в миграциях — используйте initial_data.py для этого
- Используйте миграции для изменений данных — обновление значений, добавление записей и т.д.
- Планируйте миграции тщательно, поскольку откат не поддерживается
Управление версиями
- Система автоматически отслеживает версию каждого плагина отдельно
- Миграции применяются в порядке версий (1.0.1, 1.0.2, 2.0.0 и т.д.)
- Если плагин понижается в версии, система обнаружит это, но не будет автоматически откатывать
- Примечание: Функциональность отката не поддерживается — миграции только вперед
Устранение неполадок
Миграция не удалась
Если миграция не удалась:
- Проверьте логи для получения подробных сообщений об ошибках
- Исправьте код миграции
- Перезапустите бота для повторной попытки миграции
Несоответствие версий
Если вы видите предупреждения о несоответствии версий:
- Проверьте, что ваш info.json имеет правильную версию
- Убедитесь, что файлы миграций существуют для всех промежуточных версий
- Проверьте логи для получения подробной информации о статусе миграций
Проблемы с базой данных
Если вы столкнулись с проблемами, связанными с базой данных:
- Убедитесь, что ваш код миграции использует правильные методы хранилища
- Проверьте, что все обязательные поля предоставлены при создании записей
- Убедитесь, что ваша миграция не конфликтует с существующими данными