Восстановление хранилища сессий
Все разговоры Hermes хранит в одном SQLite-файле на профиль — state.db. Рядом лежат два
служебных файла, которыми SQLite управляет сам: state.db-wal (журнал упреждающей записи,
write-ahead log) и state.db-shm. Работать с этим файлом одновременно могут несколько
процессов Hermes — шлюз, десктопное приложение, дашборд, cron и команды CLI пишут в него
через собственные блокировки SQLite, и это безопасно.
Небезопасно одно: переписывать хранилище, пока в него пишет другой процесс. Если так случилось, процессы, у которых осталась старая копия журнала, намеренно перестают писать, и на каждый ход отвечают сообщением примерно такого вида:
another Hermes process still holds an old copy of the session database’s write-ahead log, so Hermes stopped writing to keep the file safe …
По-русски: другой процесс Hermes всё ещё держит старую копию журнала базы сессий, и Hermes перестал писать, чтобы не повредить файл. Ссылка из этого сообщения ведёт как раз сюда. Данные при этом не теряются — отказ и нужен для того, чтобы ничего не пропало.
Починка в три шага
-
Завершите все процессы Hermes этого профиля. Десктопное приложение, шлюз, дашборд, cron:
hermes gateway stop # для именованного профиля добавьте -p <profile>затем закройте десктопное приложение через его меню и остановите дашборд (
hermes dashboard --stop) или свой сервис, если он у вас есть. Перезапустить один из них мало: пока хоть один процесс держит старый журнал, все новые будут отказывать. -
Спросите doctor, кто ещё держит журнал.
hermes doctor # для именованного профиля добавьте -p <profile>Пока кто-то держит выведенный из работы журнал, doctor печатает каждого такого держателя в виде
PID N (command)с той же рекомендацией и пропускает свои проверки здоровья и любую работу--fix, чтобы самому не стать ещё одним писателем. Остановите перечисленные процессы и запускайте doctor снова, пока строка не исчезнет. -
Запустите Hermes заново (сначала один процесс — шлюз или десктопное приложение) и отправьте сообщение ещё раз. Разговор продолжится с того места, где остановился.
Чего не делать
- Не запускайте
hermes doctor --fix, пока процессы работают. Doctor отказывается делать чекпоинт, если видит процесс со старым журналом, но на хосте, где он не может заглянуть в список процессов, путь--fixокажется ровно тем вторым писателем, из-за которого всё и началось. - Не удаляйте
state.db-walиstate.db-shm. В журнале лежат закоммиченные разговоры, которых ещё нет вstate.db. Удаление — единственное действие, которое превращает отказ в настоящую потерю данных. - Не копируйте один
state.db. Три файла — это единый образ. Пользуйтесь снимком (hermes backup) илиhermes sessions recover, но никогда неcp state.db somewhere/. - Не просите агента это починить. Его собственная сессия лежит в том же хранилище, и он упрётся в тот же отказ.
Команды обслуживания отказываются работать, пока кто-то пишет
hermes sessions optimize, hermes sessions optimize-storage и hermes sessions prune
переписывают хранилище (VACUUM, перестроение полнотекстового индекса, массовое удаление).
Запуск любой из них под живым шлюзом — как раз тот путь, которым целый парк агентов
приходит к описанному выше отказу. Поэтому теперь они сначала проверяют и отказываются
работать, если базу держит другой процесс:
Refusing `hermes sessions optimize-storage`: another process is using ~/.hermes/state.db.
PID 41230 (hermes gateway run): state.db, state.db-shm, state.db-wal
PID 41355 (hermes serve --profile work): state.db-wal
Rewriting the database under a live writer is how every agent ends up refusing turns with the
retired state.db-wal error. Nothing is lost.
Stop them first (`hermes gateway stop`, quit the Desktop app, pause cron), then re-run.
Override with --force if you accept the risk.
Предпросмотр через --dry-run не блокируется никогда. --force запускает команду в любом
случае — используйте его, только если точно знаете, что перечисленные процессы простаивают
(например, это читатель, которого вы запустили сами). Та же проверка срабатывает, когда вы
вводите sessions optimize в консоли десктопного приложения.
Какие файлы бывают рядом со state.db
| Файл или каталог | Что это | Что делать |
|---|---|---|
state.db-wal, state.db-shm | Живой журнал упреждающей записи SQLite и его индекс в разделяемой памяти. Большой -wal — норма, пока работает шлюз или десктопное приложение. | Не трогайте. На следующем чекпоинте они уменьшатся сами. |
state.db.retired-wal-<timestamp>-<pid>/ | Снимок копии журнала, которую держал процесс в момент отказа от записи, плюс manifest.json с её описанием. Это материал для разбора, а не бэкап, который можно восстанавливать вслепую. | Сохраните. Если после восстановления пропали разговоры прямо перед инцидентом, приложите каталог к баг-репорту: по manifest.json мейнтейнер определит, ложатся ли эти кадры поверх текущего файла. |
state.db.pre-update-emergency-<timestamp>.bak | Снимок, который делает программа обновления десктопного приложения, прежде чем трогать хранилище. | Держите, пока какое-то время не поработаете с обновлённым приложением. Восстанавливайте только при остановленных процессах Hermes, и сначала — hermes sessions recover --source <file> --inspect-only. |
state.db.corrupt.<timestamp>.bak, *.malformed-backup | Копии файла, который Hermes нашёл повреждённым перед починкой или карантином. | Не восстанавливайте их поверх state.db — в них то же повреждение. Сохраните для отчёта; когда всё придёт в норму, их можно удалить. |
state-snapshots/ | Быстрые снимки, которые делают hermes update и hermes backup. | Восстанавливайте при остановленных процессах Hermes; см. hermes backup. |
Если три шага не помогли
Все процессы Hermes остановлены, hermes doctor больше никого не показывает, а шлюз после
запуска всё равно отказывается писать? Тогда, возможно, повреждён сам файл. Снова
остановите всё и осмотрите его без записи:
hermes sessions recover --source ~/.hermes/state.db --inspect-only
--inspect-only никогда не изменяет файл. Если команда сообщит, что хранилище можно
восстановить, выполните напечатанную ею команду или восстановите самый свежий снимок из
state-snapshots/. Как всё это устроено внутри, описано в руководстве разработчика:
Восстановление базы состояния и
Хранилище сессий.