simbiot-harness/scripts/safe-restart.sh

74 lines
No EOL
4.3 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# t-260929210755 / закрытие эскалации e-260929234911: рестарт демона лестницы
# БЕЗ убийства живых LLM-воркеров (рестарт при живом воркере = застрявшая
# running-задача, тот самый инцидент). Ждём «тихого окна» — нет процессов
# harness/_llm_worker.py, с подтверждением 3с, потом systemctl restart.
#
# Гарантия на гонку «проверил → стартовал новый воркер → рестарт»: orphan-requeue
# (commit 42743f9) возвращает running-задачи с мёртвым воркером в очередь —
# даже худший случай не теряет работу, просто повторит её.
#
# Использование: scripts/safe-restart.sh [max_wait_sec] (по умолчанию 3600)
set -u
MAX_WAIT="${1:-3600}"
LOG="${SIMBIOT_RESTART_LOG:-/tmp/simbiot-safe-restart.log}"
SERVICE="${SIMBIOT_SERVICE:-simbiot-harness}"
# якорь в конец cmdline: не матчит sh -c команды, которые лишь УПОМИНАют воркера
PAT='/harness/_llm_worker\.py$'
deadline=$(( $(date +%s) + MAX_WAIT ))
echo "[$(date -u '+%F %T')] safe-restart: ждём тихое окно (макс ${MAX_WAIT}s), сервис ${SERVICE}" >> "$LOG"
while :; do
if ! pgrep -f "$PAT" > /dev/null; then
sleep 3 # окно должно быть устойчивым
if ! pgrep -f "$PAT" > /dev/null; then
echo "[$(date -u '+%F %T')] safe-restart: тихое окно поймано" >> "$LOG"
break
fi
fi
if [ "$(date +%s)" -ge "$deadline" ]; then
echo "[$(date -u '+%F %T')] safe-restart: тихого окна нет ${MAX_WAIT}s — рестарт всё равно (orphan-requeue подхватит)" >> "$LOG"
break
fi
sleep 5
done
if systemctl restart "$SERVICE"; then
echo "[$(date -u '+%F %T')] safe-restart: демон ${SERVICE} перезапущен" >> "$LOG"
else
echo "[$(date -u '+%F %T')] safe-restart: FAIL — systemctl restart ${SERVICE}" >> "$LOG"
exit 1
fi
# ── пост-рестарт верификация: сек-тик НОВОГО демона отвечает на команду без LLM ──
# (инъекция синтетического сообщения в стор; через N секунд в сторе должен быть
# ReplySent от сек-тика — это доказывает, что новый код жив в продакшене)
sleep 6 # демон поднимается, первые сек-тики проходят
VERIFY_MSG_ID="${SIMBIOT_VERIFY_MSG_ID:-990102}"
cd /root/simbiot-harness || exit 1
./venv/bin/python - "$VERIFY_MSG_ID" <<'EOF' >> "$LOG" 2>&1
import sys, time, sqlite3
mid_num = sys.argv[1]
from harness import es, tg_inbox
mid = tg_inbox.receive_message({'update_id': int(mid_num), 'message': {
'message_id': int(mid_num),
'chat': {'id': 7569223131},
'from': {'id': 7569223131, 'username': 'alex_test'},
'text': '/лестница', 'date': int(time.time())}})
print(f"verify: инъекция {mid} (/лестница), ждём ответ сек-тика демона...")
time.sleep(8)
db = sqlite3.connect(es.DB_PATH); db.row_factory = sqlite3.Row
rows = db.execute("SELECT event_type, data FROM events WHERE aggregate_id=? ORDER BY id", (mid,)).fetchall()
types = [r["event_type"] for r in rows]
ok = "ReplySent" in types and "CommandHandled" in types
for r in rows:
print(f"verify: {r['event_type']} → {r['data'][:120]}")
print(f"verify: {'OK — сек-тик нового демона ответил на команду без LLM' if ok else 'FAIL — ответа нет, смотреть журнал демона'}")
sys.exit(0 if ok else 2)
EOF
rc=$?
if [ "$rc" -eq 0 ]; then
echo "[$(date -u '+%F %T')] safe-restart: верификация ПРОЙДЕНА (сек-тик отвечает на команды)" >> "$LOG"
elif [ "$rc" -eq 2 ]; then
echo "[$(date -u '+%F %T')] safe-restart: верификация ПРОВАЛЕНА — смотри журнал демона!" >> "$LOG"
journalctl -u "$SERVICE" --since "2 minutes ago" --no-pager | tail -20 >> "$LOG"
fi
exit "$rc"