# Постоянное хранение

> Как сервис LMSP хранит своё состояние, со встроенной базой SQLite, перечнем таблиц, транзакционными правилами для задач и событий, сроком хранения и восстановлением при запуске.

Source: https://madeforagent.com/ru/lmsp/1.0/persistence/
Language: ru
Specification: LMSP 1.0 (draft)
Updated: 2026-11-08

## 11.1 Хранилище {#storage}

Сервису **СЛЕДУЕТ** хранить своё состояние во встроенной базе данных [SQLite](https://www.sqlite.org/). Предлагаемый набор таблиц:

| Таблица | Содержимое |
| --- | --- |
| `service_config` | Идентичность и конфигурация сервиса. |
| `clients` | Сопряжённые клиенты, хеши токенов и области доступа. |
| `models` | Метаданные моделей и дайджесты содержимого. |
| `responses` | Сохранённые ответы. |
| `tasks` | Асинхронные задачи. |
| `task_events` | Журнал событий каждой задачи с порядковыми номерами. |
| `idempotency_keys` | Ключи идемпотентности, дайджесты запросов и результаты. |

Файлы моделей **ДОЛЖНЫ** оставаться вне базы данных. База хранит только метаданные и дайджесты содержимого.

Имена таблиц и их структура — решение реализации. То, что клиенты могут наблюдать и что должно быть совместимо, — это поведение, описанное в двух следующих разделах.

## 11.2 Правила {#rules}

Какое бы хранилище ни использовал сервис, действуют такие правила:

- Сервис **ДОЛЖЕН** сохранять задачу до того, как вернёт `202 Accepted`.
- Сервис **ДОЛЖЕН** обновлять порядковые номера событий и статус задачи в одной транзакции.
- Сервис **ДОЛЖЕН** делать переход отмены атомарным, чтобы избежать гонки, при которой задача сначала отменяется, а потом завершается.
- Сервису **СЛЕДУЕТ** хранить завершённые задачи и события в течение настраиваемого срока хранения.
- Сервис **НЕ ДОЛЖЕН** удалять незавершённые задачи при очистке журналов.
- Сервис **ДОЛЖЕН** при запуске просматривать оставшиеся задачи `queued`, `loading`, `running` и `cancelling` и применять к каждой её политику перезапуска ([раздел 7.5](https://madeforagent.com/ru/lmsp/1.0/tasks.md#restart)).

## 11.3 Восстановление при запуске {#recovery}

В таблице показано состояние, в которое переводится оставшаяся задача в соответствии с её политикой `on_restart`:

| Состояние при запуске | `fail` | `retry` | `resume` |
| --- | --- | --- | --- |
| `queued` | `failed` | `queued` | `queued` |
| `loading` | `failed` | `queued` | `queued` |
| `running` | `failed` | `queued` | `running`, продолжение со снимка состояния |
| `cancelling` | `cancelled` | `cancelled` | `cancelled` |

Задача, переведённая в `failed`, получает код ошибки `server_restarted` и событие `response.failed`. Задача, переведённая в `cancelled`, получает событие `response.cancelled`. Новое состояние и его событие записываются в одной транзакции ([раздел 11.2](https://madeforagent.com/ru/lmsp/1.0/persistence.md#rules)).
