# 持久化

> LMSP 服務如何儲存自己的狀態：嵌入式 SQLite 資料庫、建議保留的表、任務與事件的交易規則、保留期，以及啟動時的恢復。

Source: https://madeforagent.com/zh-tw/lmsp/1.0/persistence/
Language: zh-TW
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/zh-tw/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/zh-tw/lmsp/1.0/persistence.md#rules)）。
