Для AI-агентов: markdown этой страницы — /docs-content/infra/galaxy-sleep.md индекс документации — /llms.txt

Сон и пробуждение Galaxy-приложения

Galaxy-приложение засыпает по простою вместе с галактикой-носителем, и на время сна его контейнер остановлен. Эта страница описывает, что именно останавливается, какие поля показывают настоящее состояние, чем приложение поднять и сколько это занимает.

Что останавливается · Поля состояния · Чем поднять · Логи · Окно по расписанию

Что останавливается во сне

Приложение живёт в контейнере на общем хосте — галактике. Спать могут обе части, и это разные состояния.

Что спит Как это выглядит Что нужно, чтобы поднять
Контейнер приложения, галактика работает Приложение не отвечает, соседние приложения той же галактики работают Запуск контейнера — секунды
Галактика вместе со всеми контейнерами Не отвечает ни одно приложение этой галактики Загрузка машины галактики, затем запуск контейнера — минуты

Постоянный том /data сон переживает. Пробуждение запускает тот же контейнер, а не создаёт новый, поэтому строки, которые приложение записало в свой поток вывода до сна, доступны и после пробуждения. Полностью новый контейнер появляется только при повторной загрузке кода — вот она журнал предыдущего контейнера не сохраняет.

Поля status и reachability отвечают на разные вопросы

Поле status в ответе GET /v1/infra/servers/:id — это состояние учётной записи приложения на платформе. Пробуждение переводит запись в running в конце, когда контейнер уже запущен, поэтому во время подъёма галактики запись остаётся в sleeping — на холодной машине это занимает минуты. Обратное расхождение тоже возможно: запись может числиться в running, пока контейнер уже не работает.

Поэтому рядом идёт блок reachability — он отвечает на вопрос «может ли приложение ответить прямо сейчас». Блок приходит только у приложения, kind равен GALAXY_APP, у остальных типов серверов там null.

JSON
{
  "success": true,
  "data": {
    "id": "e22bb297-8a0a-4597-9b42-47d059cd1090",
    "kind": "GALAXY_APP",
    "status": "sleeping",
    "reachability": {
      "effectiveStatus": "running",
      "hostStatus": "running",
      "hostTunnel": "CONNECTED",
      "container": "running",
      "forwarder": "active",
      "publicEntry": "live",
      "probe": "ok",
      "probedAt": "2026-08-12T13:24:58.117Z"
    }
  }
}

Показаны поля, относящиеся к сну. Полный ответ — GET /v1/infra/servers/:id.

Поле Описание
effectiveStatus Сводный ответ о доступности — running, sleeping, waking, unreachable или unknown. Как он выводится, показано в таблице ниже
hostStatus Состояние галактики-носителя в том же наборе значений, что и status сервера
hostTunnel Соединение галактики с платформой — CONNECTED, DISCONNECTED или NONE
container Контейнер приложения — running, stopped или unknown. Значение unknown означает, что платформа не смогла посмотреть, а не что контейнер остановлен
forwarder Маршрутизация к контейнеру на хосте — active, inactive или unknown. Во сне останавливается вместе с контейнером
publicEntry Публичный адрес приложения — live (у шлюза есть живой туннель на поддомен приложения), no-tunnel (туннеля нет, снаружи адрес не обслуживается) или unknown (спросить шлюз не удалось). Значение unknown вердикт никогда не ухудшает
probe Чем закончился живой опрос хоста — ok, host-down (галактика спит или недоступна, опрос не отправлялся), host-busy (хост занят другой операцией), failed или not-attempted
probedAt Время опроса по стандарту ISO 8601. Значение null означает, что опроса не было

Как складывается effectiveStatus:

Состояние effectiveStatus
Галактика загружается waking
Галактика спит sleeping
Галактика работает, контейнер остановлен sleeping
Галактика работает, контейнер работает, маршрутизация активна, у публичного адреса есть туннель running
Галактика работает, контейнер работает, маршрутизация активна, туннеля у публичного адреса нет unreachable
Галактика работает, контейнер работает, маршрутизация остановлена unreachable
Галактика в ошибке либо потеряла соединение с платформой unreachable
Посмотреть не удалось unknown

Публичный вход проверяется отдельно. Контейнер и маршрутизация измеряются на самой галактике, а последний участок пути до https://app-XXXX.vibecode.bitrix24.tech — это туннель приложения на шлюзе, и на галактике его не видно: запущенный юнит маршрутизации означает, что его запустили, а не что он дозвонился до шлюза. Поэтому приложение с живым контейнером и активной маршрутизацией, но без туннеля, отвечает unreachable, а не running — снаружи такой адрес не обслуживается. Если состояние шлюза узнать не удалось, publicEntry равен unknown и вердикт остаётся прежним: «не смогли посмотреть» — это не «ничего не работает».

Важно: живой опрос хоста платформа делает только когда галактика работает и соединена с платформой. Спящую галактику чтение состояния не будит, поэтому у спящей галактики container и forwarder всегда unknown, а probe равен host-down. Результат опроса платформа держит несколько секунд и отдаёт из памяти: опрос занимает канал команд, общий для всех приложений галактики, поэтому частый опрос состояния его не занимает.

Чем поднять спящее приложение

Способ Что делает
POST /v1/infra/servers/:id/wake Поднимает приложение через хост. При необходимости запускает галактику, затем стартует контейнер
POST /v1/infra/servers/:id/start То же самое. Отдельного смысла у двух вызовов для приложения нет
Загрузка кода Поднимает галактику сама и оставляет приложение работающим
Обращение к адресу приложения Запрос через шлюз поднимает приложение и до готовности отвечает кодом BH_SERVER_WAKING с заголовком Retry-After — подробности в Авторизации в приложении на Black Hole
Доставка события портала Платформа поднимает приложение перед доставкой

Ответ на вызов пробуждения приходит сразу, а не по готовности: у приложения нет своей облачной машины, и параметр ?wait=true ожидания здесь не даёт. Готовность проверяйте опросом GET /v1/infra/servers/:id по полю reachability.effectiveStatus — значение waking означает, что галактика ещё загружается.

Сколько ждать: подъём холодной галактики платформа ждёт до 15 минут и столько же готова ждать от вызывающего. Точное значение бюджета приходит в ответе на чтение логов спящего приложения, поле recovery.coldBootBudgetSeconds. Приложение на уже работающей галактике стартует за секунды.

Запрет пробуждения на хосте блокирует оба вызова, и /start его не снимает. Коды отказов — в таблице жизненного цикла на странице Galaxy-приложение.

Логи спящего приложения

Чтение GET /v1/infra/servers/:id/logs не будит ни приложение, ни галактику. Пока галактика спит или недоступна, ответ приходит со статусом 200, пустым массивом data.logs и двумя диагностическими полями.

JSON
{
  "success": true,
  "data": {
    "logs": [],
    "lines": [],
    "hint": "Galaxy host is asleep or unreachable, so the container log cannot be read right now. …",
    "recovery": {
      "reason": "The galaxy host carrying this container is not RUNNING + CONNECTED. …",
      "recoveryAction": "POST /v1/infra/servers/e22bb297-8a0a-4597-9b42-47d059cd1090/wake",
      "logsPreserved": true,
      "coldBootBudgetSeconds": 900,
      "poll": "GET /v1/infra/servers/e22bb297-8a0a-4597-9b42-47d059cd1090 (read `reachability`)",
      "wakeSchedule": { "available": true, "code": null }
    }
  }
}
Поле Описание
hint Та же подсказка обычным текстом, одной строкой. Текст зависит от того, может ли вызывающий позвать пробуждение: когда может — называет вызов пробуждения; когда нет — адреса пробуждения не называет вовсе, зато называет ровно то условие, которое сработало именно у него. Второй путь подъёма подсказка называет только тогда, когда он этому вызывающему доступен, то есть вместе с полем recovery.deliveryWakesHost, а не всегда
recovery.reason Почему журнал сейчас не читается
recovery.recoveryAction Вызов ПРОБУЖДЕНИЯ. Поле условное — его может не быть. Отсутствует всякий раз, когда вызывающий пробуждение позвать не может. Перечень таких состояний открыт и растёт, поэтому ветвитесь по НАЛИЧИЮ поля, а не по списку. Сегодня в него входят режим «только чтение», ключ Коворка/Кода, выключенный пилот галактик, ключ обслуживания агента, владелец с идущим удалением аккаунта и доступ к приложению по связи, когда сервером владеет другой ключ. Сюда же входит запрет пробуждения на самом ХОСТЕ галактики: он отбивает пробуждение любому вызывающему, включая полноправного владельца, поэтому в этом состоянии поля тоже нет. Проверяйте наличие ключа перед обращением: в этом состоянии адреса пробуждения нет ни в одном поле ответа — ни здесь, ни в hint. Важно: обратное не гарантия. НАЛИЧИЕ поля означает, что пробуждение не отбито ни по вызывающему, ни запретом на хосте, — но не что вызов состоится в любом случае: остаются отказы по СОСТОЯНИЮ пары, которые ответ логов не предсказывает (422, когда приложение не в том статусе или хост не загрузился, 404, когда галактика осиротела). Обрабатывайте такой отказ, а не считайте наличие поля гарантией
recovery.logsPreserved Значение true означает, что строки, записанные до сна, доступны после пробуждения
recovery.coldBootBudgetSeconds Бюджет подъёма холодной галактики в секундах
recovery.poll Чем проверять готовность вместо повторного чтения логов. Поле условное — его может не быть. Отсутствует, когда GET /v1/infra/servers/{id} отказывает самому вызывающему: у ключа обслуживания агента этого маршрута нет в перечне, а у владельца с идущим удалением аккаунта он живёт в замороженном контуре, в отличие от чтения журнала. Нет поля — просто перечитайте журнал позже, подсказка так и говорит
recovery.deliveryWakesHost Второй путь подъёма. Поле условное вдвойне: приходит, только когда пробуждение вызывающему недоступно И деплой ему при этом доступен. action — вызов деплоя, cost — его цена словами. Деплой на спящее галакси-приложение поднимает хост сам, но это ВЫКЛАДКА КОДА и расход баланса, а не пробуждение — ради одного лишь чтения журнала его звать не надо. Важно: отсутствие поля означает, что и этот путь закрыт: послабление режима «только чтение» снимает у деплоя гейт РЕЖИМА и только его, а ключу Коворка/Кода, выключенному пилоту и ключу обслуживания агента деплой отказывают те же двери, что и пробуждению. Поле отсутствует и при запрете пробуждения на хосте — деплой спящий хост с таким запретом НЕ поднимает, а отвечает 502
recovery.wakeSchedule Доступно ли окно пробуждения по расписанию этому вызывающему: и пригодность самого приложения, и право вызывающего на запись — одним вердиктом. Поле available — ответ, поле code при отказе несёт тот же код, которым ответит создание окна. Когда recoveryAction отсутствует, поле приходит available: false с кодом той двери, которая отбила пробуждение: создание окна — та же запись и отбивают её те же двери. Исключение — дверь окна, которая проверяется раньше этой: тогда code называет дверь окна, и hint называет ту же дверь, а не говорит, что окно отбивает то же условие, что и пробуждение. Важно: у окна есть и ДВЕ собственные двери, которых у пробуждения нет, поэтому code может назвать отказ, которого в списке дверей пробуждения не найти, а available: false может прийти и при наличии recoveryAction. Первая проверяется раньше всех остальных: маршрут окна отсутствует в перечне маршрутов ключа внешнего участника, тогда как пробуждение, деплой и чтение журнала в этом перечне есть, — EXTERNAL_COLLABORATOR_KEY_OUT_OF_SCOPE. Вторая проверяется позже дверей режима, заморозки, Коворка и пилота, но РАНЬШЕ проверки владения сервером: маршруту окна нужен скоуп vibe:infra, которого чтение логов и пробуждение не требуют, поэтому до этого отказа доходит и обычный ключ без скоупа — INFRA_SCOPE_REQUIRED, и лечится он выдачей скоупа, а не сменой режима. Владение проверяется после скоупа, поэтому вызывающему, пришедшему по связи приложения и не несущему скоуп, придёт INFRA_SCOPE_REQUIRED, а не NOT_FOUND

Порядок действий: поднять приложение вызовом из recovery.recoveryAction, дождаться reachability.effectiveStatus равного running, повторить чтение логов.

Если поля recoveryAction в ответе нет — пробуждение откажут. Причина бывает двух родов, и hint называет ту, что сработала: либо дверь самого вызывающего (перечень ниже), либо запрет пробуждения на ХОСТЕ галактики — тогда ключ ни при чём, отказ придёт любому, и снимать запрет идёт владелец аккаунта. Вызов пробуждения в этом состоянии отвечает 403 SERVER_WAKE_BLOCKED, а пока у аккаунта просрочен доступ — 402 с кодом подписочной или тарифной стены. Окно по расписанию в этом состоянии создать можно, но хост оно не поднимет: запрет действует и на пробуждение по расписанию. Адреса пробуждения нет и в прозе: в этом состоянии ответ намеренно не называет ни POST …/wake, ни создание окна по расписанию — окно отбивает та же дверь. hint вместо адреса называет ровно то условие, которое сработало у него самого, а не список через «или», — и называет ПЕРВОЕ по порядку, в каком двери отбивают на самом деле. Порядок такой: у ключа обслуживания агента пробуждения нет в перечне маршрутов; при идущем удалении аккаунта пробуждение закрыто целиком, и смена ключа не поможет — заморожен владелец, а не ключ (доставка при этом остаётся открытой, см. ниже про второй путь); режим ключа переключается по Режиму доступа; ключу Коворка/Кода управляющий контур закрыт целиком; выключенный пилот галактик снимает администратор аккаунта; и последняя — доступ к приложению по связи, когда сервером владеет другой ключ: пробуждение проверяет владение строже, чем чтение журнала, поэтому такому вызывающему оно отвечает 404, и помогает только вызов ключом-владельцем сервера.

У части вызывающих выход всё же есть, и это не пробуждение. Ключу в режиме «только чтение» разрешён деплой на свой сервер, а деплой на спящее галакси-приложение поднимает хост сам. Тот же путь открыт ещё двум вызывающим, которым отказано в пробуждении: владельцу с идущим удалением аккаунта (заморозка стоит на плагине /v1/infra, а доставка живёт в другом) и тому, кого пустили по связи приложения (владение доставка проверяет мягче, чем пробуждение). Закрыт этот путь ровно трём: ключу Коворка/Кода, ключу обслуживания агента и вызывающему на аккаунте с выключенным пилотом галактик. Когда этот путь открыт, платформа называет его машинно — полем recovery.deliveryWakesHost (action — вызов, cost — цена словами), и цена тут не формальность: это выкладка кода и расход баланса Вайбкод, а не пробуждение. Звать его ради одного лишь чтения журнала не надо.

Открыт он не всем, и поле это показывает. Послабление для режима «только чтение» снимает у деплоя гейт РЕЖИМА и только его. Ключу Коворка/Кода управляющий контур закрыт целиком, при выключенном пилоте галактик отказывают любые не-GET по этому семейству, а у ключа обслуживания агента деплоя нет в его перечне маршрутов — всем троим POST …/deploy ответит отказом ровно так же, как и пробуждение. Поэтому проверяйте наличие deliveryWakesHost, а не предполагайте его: нет поля — открытого пути нет, и надо менять условие из hint. Важно: обратное тоже не гарантировано, ровно как у recoveryAction: наличие поля означает, что деплой не отбит ни по identity и режиму ключа, ни запретом на хосте. Оно не отвечает за состояние счёта НА МОМЕНТ ВЫЗОВА: заморозка баланса закрывает всё семейство /v1/infra целиком (402 ACCOUNT_FROZEN), и если она наступит после этого чтения, названный action получит именно её — тем более что деплой тратит баланс по построению. Пока условие не изменилось, повторять чтение логов в цикле смысла нет: ответ не изменится.

Окно пробуждения по расписанию

Окно пробуждения поднимает приложение по расписанию, без вызова руками. Доступно оно не каждому приложению, и проверять это следует по ответу платформы, а не по общему правилу: поле recovery.wakeSchedule в ответе на чтение логов спящего приложения даёт готовый ответ для конкретного приложения, а при отказе — его код.

Ответ этот — и про приложение, и про вызывающего сразу. Создание окна остаётся записью, поэтому ключу в режиме «только чтение», ключу Коворка/Кода и порталу с выключенным пилотом галактик оно откажет; в этих состояниях поле приходит available: false с кодом отбившей двери. Пробуждение — хороший первый признак: нет recovery.recoveryAction — окна этому вызывающему тоже не создать. Но признак этот не полный, потому что у окна есть две двери, которых у пробуждения нет: маршрут отсутствует в перечне ключа внешнего участника (EXTERNAL_COLLABORATOR_KEY_OUT_OF_SCOPE) и требует скоуп vibe:infra, которого пробуждение не требует (INFRA_SCOPE_REQUIRED). Любая из двух откажет в окне и тому, кто приложение разбудить может, — поэтому читайте само поле recovery.wakeSchedule, а не выводите его из recoveryAction.

Приложение в галактике отказ ALWAYS_ON_CONFLICT не получает: тариф оно не выбирает, а наследует от галактики, и режимом «Всегда онлайн» платформа его не считает. Это касается и агентов, и ботов: своего таймера простоя у них нет, но окно пробуждения им доступно на общих условиях. Остальные отказы окна при этом действуют — например, WAKE_SCHEDULE_GALAXY_DISABLED, когда на платформе выключена возможность для приложений галактики.

Список окон, создание, изменение и удаление — Пробуждение по расписанию.

Смотрите также