Files
awoooi/docs/adr/ADR-007-data-retention-policy.md
OG T 7478dc0254 feat(phase6-9): Complete modular architecture and Agent Teams
Phase 6.4 - Modular Architecture:
- Add lewooogo-brain adapters for LLM providers
- Add lewooogo-data dual memory (Redis + PostgreSQL)
- Implement consensus engine for multi-agent decisions
- Add incident memory service for historical context

Phase 9 - Agent Teams (Claude Agent SDK):
- Add base agent class with Claude Sonnet 4 integration
- Implement action planner, blast radius, and security agents
- Add agent API endpoints and proposal workflow
- Integrate ADR-009 OpenClaw Agent Teams architecture

DevOps & CI/CD:
- Add GitHub Actions CI/CD workflows (ci.yaml, cd.yaml)
- Add pre-commit hooks and secrets baseline
- Add docker-compose for local development
- Update Kubernetes network policies

Frontend Improvements:
- Add auto-healing error boundary component
- Update i18n messages for agent features
- Enhance dual-state incident card with execution feedback

Documentation:
- Add 7 ADRs covering MCP, design system, architecture decisions
- Update ARCHITECTURE_MEMORY.md with modular design
- Add GLOBAL_RULES.md and SOUL.md for project identity

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-23 18:40:36 +08:00

235 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-007: 資料保留策略
> **狀態**: 已接受
> **日期**: 2026-03-20
> **決策者**: CEO, CTO, CIO
---
## 背景
需要定義各類型資料的保留時間 (TTL),確保:
1. 系統效能不因資料累積而下降
2. 重要資料有足夠的回溯時間
3. 儲存成本可控
### CEO 指示 #7
> 熱資料 (Redis/即時查詢) TTL 7 天 => 初期是否也保留 6 個月?要確認數據量有多大?
---
## 決策
### 資料分層策略
```
┌─────────────────────────────────────────────────────────┐
│ Layer 1: 熱資料 (Redis) │
│ TTL: 7-30 天 │
│ 用途: 即時查詢、快取、Session │
│ 預估容量: ~500MB │
└─────────────────────────────────────────────────────────┘
│ 過期後
┌─────────────────────────────────────────────────────────┐
│ Layer 2: 溫資料 (PostgreSQL) │
│ TTL: 6 個月 (CEO 指示) │
│ 用途: 歷史查詢、報表、分析 │
│ 預估容量: ~5GB/月 │
└─────────────────────────────────────────────────────────┘
│ 過期後
┌─────────────────────────────────────────────────────────┐
│ Layer 3: 冷資料 (歸檔) │
│ TTL: 永久 (審計日誌) / 1 年 (一般) │
│ 用途: 合規、稽核、法律要求 │
│ 預估容量: ~10GB/年 │
└─────────────────────────────────────────────────────────┘
```
### 各資料類型 TTL 定義
#### Redis 熱資料 (Layer 1)
| 資料類型 | TTL | 說明 | 預估大小 |
|---------|-----|------|---------|
| Session Token | 7 天 | 用戶登入狀態 | ~1KB/session |
| Dashboard 快取 | 5 分鐘 | 即時指標聚合 | ~10KB |
| 主機狀態快取 | 30 秒 | 即時健康狀態 | ~2KB/host |
| AI 回應快取 | 1 小時 | 相同問題快取 | ~5KB/entry |
| 限流計數器 | 1 分鐘 | Rate Limiting | ~100B/user |
**Redis 容量評估**:
- 4 台主機 × 2KB = 8KB (即時狀態)
- 100 用戶 × 1KB = 100KB (Session)
- Dashboard 快取 = 50KB
- AI 快取 (1000 條) = 5MB
- **總計: ~10MB (遠低於 Redis 16GB 容量)**
> ✅ **結論**: Redis 熱資料保持短 TTL (7-30 天) 是合理的,不需要延長至 6 個月。
> Redis 用於快取和即時查詢,歷史資料應存放在 PostgreSQL。
#### PostgreSQL 溫資料 (Layer 2)
| 資料類型 | TTL | 說明 | 預估大小 |
|---------|-----|------|---------|
| 監控指標 | 6 個月 | CPU/Memory/Disk 歷史 | ~1GB/月 |
| 告警記錄 | 6 個月 | 歷史告警 | ~100MB/月 |
| 部署記錄 | 6 個月 | Pipeline 執行歷史 | ~50MB/月 |
| 工單記錄 | 6 個月 | 處理歷史 | ~20MB/月 |
| AI 對話記錄 | 6 個月 | Copilot 歷史 | ~500MB/月 |
| 用戶操作記錄 | 6 個月 | 行為追蹤 | ~200MB/月 |
**PostgreSQL 容量評估**:
- 每月增量: ~2GB
- 6 個月累計: ~12GB
- **總計 (含索引): ~20GB**
> ✅ **結論**: PostgreSQL 溫資料保留 6 個月,符合 CEO 指示,容量可控。
#### 冷資料歸檔 (Layer 3)
| 資料類型 | TTL | 說明 |
|---------|-----|------|
| 審計日誌 | 永久 | 合規要求,不可刪除 |
| 財務記錄 | 7 年 | 法律要求 |
| 安全事件 | 3 年 | 資安稽核 |
| 系統設定變更 | 1 年 | 變更追蹤 |
---
### 資料清理機制
#### 自動清理 Job
```python
# apps/api/app/jobs/data_cleanup.py
from datetime import datetime, timedelta
from app.database import get_db
from app.models import Metric, Alert, Deployment, AIConversation
async def cleanup_expired_data():
"""每日凌晨 3:00 執行"""
six_months_ago = datetime.utcnow() - timedelta(days=180)
async with get_db() as db:
# 清理過期監控指標
deleted_metrics = await db.execute(
delete(Metric).where(Metric.created_at < six_months_ago)
)
logger.info(f"Deleted {deleted_metrics.rowcount} expired metrics")
# 清理過期告警 (保留 acknowledged 狀態)
deleted_alerts = await db.execute(
delete(Alert).where(
Alert.created_at < six_months_ago,
Alert.status != 'archived' # 保留歸檔的告警
)
)
logger.info(f"Deleted {deleted_alerts.rowcount} expired alerts")
# ... 其他資料類型
await db.commit()
# 更新 Prometheus 指標
cleanup_records_deleted.labels(type="metrics").inc(deleted_metrics.rowcount)
cleanup_records_deleted.labels(type="alerts").inc(deleted_alerts.rowcount)
```
#### K8s CronJob
```yaml
# k8s/jobs/data-cleanup-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: awoooi-data-cleanup
namespace: awoooi-prod
spec:
schedule: "0 3 * * *" # 每日凌晨 3:00
jobTemplate:
spec:
template:
spec:
containers:
- name: cleanup
image: awoooi-api:latest
command: ["python", "-m", "app.jobs.data_cleanup"]
restartPolicy: OnFailure
```
---
### 資料量監控
#### Prometheus 指標
```yaml
# k8s/monitoring/prometheus/data-alerts.yaml
groups:
- name: data-storage-alerts
rules:
# PostgreSQL 容量警告
- alert: PostgreSQLHighUsage
expr: |
pg_database_size_bytes{datname="awoooi"} > 15 * 1024 * 1024 * 1024
labels:
severity: warning
annotations:
summary: "PostgreSQL 容量已達 15GB"
description: "目前使用 {{ $value | humanize1024 }},建議檢查資料清理 Job"
# Redis 容量警告
- alert: RedisHighMemory
expr: |
redis_memory_used_bytes{db="10"} > 1 * 1024 * 1024 * 1024
labels:
severity: warning
annotations:
summary: "Redis DB 10 記憶體使用超過 1GB"
```
---
### 儲存成本評估
| 層級 | 6 個月容量 | 儲存類型 | 成本 |
|------|-----------|---------|------|
| Redis (熱) | ~10MB | 內存 | 包含在伺服器 |
| PostgreSQL (溫) | ~20GB | SSD | 包含在伺服器 |
| 歸檔 (冷) | ~10GB/年 | HDD/S3 | ~$0.5/月 |
**結論**: 採用自建伺服器,儲存成本基本為 $0 (已攤提)。
---
## 影響
### 正面
- 資料保留策略明確,符合 CEO 6 個月要求
- Redis 維持高效能 (短 TTL)
- 歷史資料可追溯
- 儲存成本可控
### 需要注意
- 清理 Job 需要監控,確保正常執行
- 歸檔資料需要定期備份
- 審計日誌不可刪除,需永久保留
---
## 變更記錄
| 日期 | 版本 | 變更 | 作者 |
|------|------|------|------|
| 2026-03-20 | v1.0 | 初版建立 | CTO |
---
*此 ADR 記錄資料保留策略的決策過程與實作規範。*