# 讀取時過期

本頁說明 TTL 如何儲存、每一層讀取如何判斷過期，以及背景掃除涵蓋的範圍。

## TTL 的儲存方式

`Set` 把 TTL 轉成整數秒存入 `Cache.TTL`，並記錄寫入當下的 Unix 秒數 `Cache.Timestamp`（`set.go:16-25`）。

| `Set` 的 `ttl` 參數 | `Cache.TTL` | 結果 |
|---|---|---|
| `10 * time.Minute` | `600` | 600 秒後過期 |
| `0` 或負值 | `0` | 不過期 |
| `500 * time.Millisecond` | `0`（無條件捨去） | **不過期** |
| `1500 * time.Millisecond` | `1` | 1 秒後過期 |

未滿 1 秒的 TTL 會被捨去成 0，等同不設過期；Redis 端同樣以 0 寫入（無過期）。

## 過期判斷

`isExpired`（`unit.go:26-31`）：`TTL ≤ 0` 永不過期；否則 `now > Timestamp + TTL` 即過期，精度為秒。

## 每一層的處理

| 位置 | 發現過期時 | 原始碼 |
|---|---|---|
| 正常模式讀記憶體 | 刪記憶體項目＋刪本地檔，回傳 `Not found` | `get.go:28-33` |
| Fallback 模式讀記憶體 | 只刪記憶體項目，回傳 `Not found` | `get.go:68-72` |
| Fallback 模式讀檔案 | 刪檔案，回傳 `Not found` | `get.go:95-100` |
| 恢復回灌 | 過期項目不寫入 Redis | `sync.go:109` |
| Redis 本身 | 由 Redis 的 key 過期機制處理 | — |

## 背景掃除

`New` 啟動一個每 30 秒觸發的 Ticker（`sync.go:135-154`），遍歷記憶體快取，刪除過期項目與其本地檔案。

| 項目 | 行為 |
|---|---|
| 掃描範圍 | 只有記憶體快取中的鍵；從未載入記憶體的本地檔案不會被掃到 |
| 間隔 | 固定 30 秒，不可設定 |
| 停止 | `Close` 不會停止這個 Ticker |
| 跳過條件 | 只在 `New` 當下檢查一次 `isRecovering`；為 true 時整個掃除不啟動 |

## 對讀取的影響

過期資料不會被 `Get` 回傳：每一層讀取都先判斷過期再回傳。背景掃除只影響記憶體與磁碟占用，不影響讀取結果。
