# 永続化

> LMSP サービスが状態を保存する方法。組み込みの SQLite データベース、保持すべきテーブル、タスクとイベントのトランザクション規則、保持期間、起動時の復旧を定めます。

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

## 11.1 ストレージ {#storage}

サービスは、状態を組み込みの [SQLite](https://www.sqlite.org/) データベースに保存する**べきである**。推奨するテーブルの構成は次のとおりである。

| テーブル | 内容 |
| --- | --- |
| `service_config` | サービスの ID と設定。 |
| `clients` | ペアリング済みクライアント、トークンのハッシュ、スコープ。 |
| `models` | モデルのメタデータと内容のダイジェスト。 |
| `responses` | 保存済みのレスポンス。 |
| `tasks` | 非同期タスク。 |
| `task_events` | 各タスクのイベントログ。シーケンス番号付き。 |
| `idempotency_keys` | 冪等キー、リクエストのダイジェスト、結果。 |

モデルファイルはデータベースの外に置か**なければならない**。データベースが保持するのは、メタデータと内容のダイジェストだけである。

テーブル名とレイアウトは実装の選択である。クライアントが観察でき、相互運用のために必要なのは、次の 2 つの節にある動作である。

## 11.2 規則 {#rules}

サービスは、どのようなストレージを使うにしても、次のことを行う。

- `202 Accepted` を返す前に、タスクを永続化し**なければならない**。
- イベントのシーケンス番号とタスクの状態を、同じトランザクションで更新し**なければならない**。
- キャンセルの遷移をアトミックにし、タスクがキャンセルされた後に完了するという競合を避け**なければならない**。
- 完了したタスクとイベントを、設定可能な保持期間の間、保持する**べきである**。
- ログの整理の際に、未完了のタスクを削除し**てはならない**。
- 起動時に、残っている `queued`、`loading`、`running`、`cancelling` のタスクを走査し、それぞれの再起動ポリシーを適用し**なければならない**（[7.5 節](https://madeforagent.com/ja/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` イベントが付く。新しい状態とそのイベントは、1 つのトランザクションで書き込まれる（[11.2 節](https://madeforagent.com/ja/lmsp/1.0/persistence.md#rules)）。
