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