Files
CFDivePlatform/openspec/changes/archive/2026-05-25-api-performance-optimization/tasks.md
T
a620906209 bda6533105 chore:歸檔 api-performance-optimization,同步主規格
- 移至 openspec/changes/archive/2026-05-25-api-performance-optimization/
- 新增主規格:api-cache-layer、db-index-optimization
- 更新 review-lifecycle 規格(補分頁、eager load)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 00:45:08 +08:00

47 lines
3.3 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.
## 1. 基礎設施:Redis 設定
- [x] 1.1 [後端] `docker-compose.yml` 新增 `redis:alpine` service,並在 `cfdive-app` depends_on 加入 `redis`
- [x] 1.2 [後端] `.env` 設定 `CACHE_STORE=redis``REDIS_HOST=redis``REDIS_PORT=6379``.env.example` 同步補上
- [x] 1.3 [後端] `config/cache.php` 確認 redis connection 設定正確(`REDIS_HOST``REDIS_PASSWORD``REDIS_PORT`
- [x] 1.4 [後端] 執行 `docker-compose up --build`,確認 redis container 啟動,`php artisan cache:clear` 無連線錯誤
## 2. 資料庫索引補充
- [x] 2.1 [後端] 建立 migration `add_performance_indexes`,為 `notifications` 表新增 `[notifiable_type, notifiable_id, read_at]` 複合索引
- [x] 2.2 [後端] 同一 migration 為 `diving_offers` 表新增 `provider_id` 索引
- [x] 2.3 [後端] 執行 `php artisan migrate`,確認索引建立成功(可用 `SHOW INDEX FROM notifications` 驗證)
## 3. 查詢優化:ReviewController::publicList
- [x] 3.1 [後端] `ReviewController::publicList()` 加入分頁:`->paginate(min($perPage, 50))``per_page` 預設 20,從 request 取得
- [x] 3.2 [後端] 評價查詢改為 `Review::with('votes')->where(...)` eager load votes,移除獨立的 `ReviewVote::where()->pluck()` SQL
- [x] 3.3 [後端] `has_voted` 判斷改從 eager loaded `$review->votes` collection 計算(`$review->votes->contains('member_id', $memberId)`
- [x] 3.4 [後端] 評價分布統計加上 `Cache::remember("offer_review_distribution_{$offerId}", 600, fn() => ...)` 快取(TTL 10 分鐘)
- [x] 3.5 [後端] Member 新增/修改/刪除評價的 service 方法中,加入 `Cache::forget("offer_review_distribution_{$offerId}")` 快取失效
- [x] 3.6 [後端] Response 加入 Laravel 分頁 meta`current_page``last_page``per_page``total`
## 4. 查詢優化:AdminReviewController
- [x] 4.1 [後端] `AdminReviewController::index()``.get()` 改為 `.paginate(min($perPage, 100))``per_page` 預設 20
## 5. 快取層:AdminStatsController
- [x] 5.1 [後端] `AdminStatsController` 的三個 `count()` 查詢,用 `Cache::remember('admin_stats', 300, fn() => [...])` 包裹(TTL 5 分鐘)
## 6. 快取層:課程列表
- [x] 6.1 [後端] `DivingOfferController::index()` 對搜尋結果加入 `Cache::remember()` 快取,Cache key 為 `diving_offers_` + md5(serialize($request->all()))TTL 180 秒
- [x] 6.2 [後端] `DivingOfferController::store()``update()``destroy()` 加入 `Cache::flush()``Cache::forget()` 清除對應快取 key
## 7. 前端相容性調整
- [x] 7.1 [前端] `CourseDetailView.vue` 的 reviews API 呼叫確認 response 結構相容(`data.data` 現在含分頁 meta,原本是陣列)
- [x] 7.2 [前端] `ReviewsView.vue`Coach Portal)確認 API response 結構相容
## 8. 手動驗證
- [x] 8.1 [整合測試] 開啟 `GET /api/diving-offers/{id}/reviews`,確認回傳包含 `meta.total``meta.current_page` 等分頁欄位
- [x] 8.2 [整合測試] 呼叫 `GET /api/admin/stats` 兩次,確認第二次無 DB 查詢(可用 Laravel Telescope 或 query log 確認)
- [x] 8.3 [整合測試] Provider 修改課程後,再次請求課程列表確認資料已更新(快取失效正常)
- [x] 8.4 [整合測試] 執行 `SHOW INDEX FROM notifications``SHOW INDEX FROM diving_offers`,確認索引存在