Жизненный цикл
Последовательность запуска
- Главный процесс запускает воркер интеграций (
WorkerMain('integrations')) и ждётloadComplete. - Главный процесс отправляет
executeCodeс{ integration: { id, name, permissions, … }, codePath }. - Воркер создаёт
GenerateContext(), затем выполняетindex.jsаддона внутриvm.runInContext(таймаут начального выполнения: 5 секунд). - Код аддона регистрирует эндпоинты, схему настроек и обработчики событий на этапе загрузки.
Долгие операции должны продолжаться после загрузки через setTimeout, setInterval, sleep или асинхронные обработчики — не блокируйте синхронным кодом начальный запуск VM.
Когда воркер перезапускается
Воркер перезапускается, когда:
- Пользователь отключает и снова включает аддон
- Аддон переустанавливают или меняют его файлы (в зависимости от поведения приложения)
- Из кода аддона вызывается
api.restart() - Переключается режим разработчика (нужен полный перезапуск приложения/воркера, чтобы применить
isDeveloperMode)
storage.Read() / storage.Write() сохраняются между перезапусками воркера в рамках одной установки. Параметры api.config хранятся в конфиге приложения.
Корректная остановка — addon:prepare-stop
Перед тем как StreamKit+ убьёт воркер аддона, главный процесс вызывает встроенное событие addon:prepare-stop и ждёт завершения обработчика (короткий таймаут, около 2.5 секунд). Используйте его для удалённой очистки, пока ещё доступны OAuth-токен и сеть.
Когда срабатывает
- Пользователь отключает аддон в настройках
- Аддон удаляют (или деактивируют как зависимость при удалении другого аддона)
- Приложение закрывается (все integration-воркеры получают prepare-stop перед kill)
Когда не срабатывает
- Падение / disconnect воркера (нет времени на graceful-обработчик)
- Внезапное завершение процесса, когда главный процесс не может дождаться воркеров
Контракт обработчика
events.On('addon:prepare-stop', async () => {
// например поставить на паузу или отключить удалённые ресурсы (награды Twitch, вебхуки, …)
await cleanupRemoteState();
return { success: true };
});
| Деталь | Значение |
|---|---|
| Payload | {} (пустой объект) |
| Право | Не требуется |
| Таймаут | ~2.5 с — делайте работу короткой; незавершённое будет прервано, воркер убьют |
| Опционально | Обработчик можно не регистрировать; на другие аддоны это не влияет |
Не полагайтесь на это событие для данных, которые должны жить вечно — важное состояние сохраняйте через storage / api.config в обычной работе. addon:prepare-stop — для best-effort teardown на стороне внешних сервисов (пауза наград, закрытие сессий, снятие короткоживущих хуков).
См. также events.
Защита от цикла падений
Если процесс воркера падает (неперехваченное исключение, фатальная ошибка, аварийное завершение), StreamKit+ перезапускает его автоматически — как при обычном рестарте.
Чтобы избежать бесконечного цикла перезапусков, приложение отслеживает последовательные падения:
| Правило | Значение |
|---|---|
| Максимум падений подряд | 3 |
| Стабильная работа для сброса счётчика | 30 секунд после loadComplete |
Что считается падением
- Завершение или отключение процесса воркера
- Сбой, обнаруженный health check главного процесса
Что не считается падением
- Ошибки в колбэках
setTimeout/setIntervalи обработчикахevents.On— они перехватываются и логируются; воркер продолжает работу (см. Безопасность) - Плановый перезапуск через
api.restart(), отключение/включение аддона или ручной рестарт из настроек
Когда лимит достигнут
- Автоперезапуск прекращается; воркер аддона больше не запускается.
- Пользователь видит уведомление об ошибке и статус аддона в состоянии error.
- В настройках аддон остаётся включённым, но отображается бейдж Остановлен из-за ошибок (с тултипом о необходимости ручного перезапуска).
- После перезапуска приложения флаг остановки сбрасывается и аддон снова запускается автоматически.
Как восстановить работу
В рамках текущей сессии пользователь должен перезапустить аддон вручную в настройках (кнопка ↻) или отключить и снова включить его. Это сбрасывает флаг остановки и запускает новый воркер с обнулённым счётчиком падений. Перезапуск всего приложения тоже сбрасывает флаг и снова стартует включённые аддоны.
Что важно разработчику аддона
- Не используйте падение воркера как способ восстановления — после трёх падений аддон останется выключенным, пока пользователь не перезапустит его (или не перезапустит приложение).
- Держите начальную фазу загрузки
index.jsкороткой; тяжёлую или рискованную работу переносите в async-колбэки после загрузки. - Оборачивайте долгоживущий код в
try/catch; необработанные reject/throw вне обёрнутых песочницей обработчиков по-прежнему могут уронить воркер. api.restart()работает только пока аддон запущен; им нельзя перезапустить аддон, остановленный из-за цикла падений.api.getProcessStats()возвращает CPU, RAM и PID этого worker. Для CPU % нужны минимум два вызова с интервалом ~1 с; используйте для контроля утечек или вызоваapi.restart()при превышении лимитов.
Статические веб-маршруты
Когда задан manifest.web и выдано разрешение WEB_CONTENT (или ROOT), главный процесс регистрирует статические маршруты:
http://localhost:{WEB_SERVER_PORT}/addon_static/{id}/
Корень отдаёт файл web; пути из web_contents обслуживаются под тем же префиксом. Маршруты удаляются при отключении, перезапуске или удалении аддона.
Отсутствующие файлы
Если manifest.json или index.js отсутствуют по сохранённому пути установки, приложение считает аддон повреждённым: в настройках показывается баннер ошибки, настройки нельзя открыть, доступно только удаление. Триггеры оверлея/таймера, ссылающиеся на этот аддон, очищаются при запуске.