Files
beabigegg 69b81d9241 feat: implement kanban real-time sync and fix workload cache
## Kanban Real-time Sync (NEW-002)
- Backend:
  - WebSocket endpoint: /ws/projects/{project_id}
  - Project room management in ConnectionManager
  - Redis Pub/Sub: project:{project_id}:tasks channel
  - Task CRUD event publishing (5 event types)
  - Redis connection retry with exponential backoff
  - Race condition fix in broadcast_to_project

- Frontend:
  - ProjectSyncContext for WebSocket management
  - Reconnection with exponential backoff (max 5 attempts)
  - Multi-tab event deduplication via event_id
  - Live/Offline connection indicator
  - Optimistic updates with rollback

- Spec:
  - collaboration spec: +1 requirement (Project Real-time Sync)
  - 7 new scenarios for real-time sync

## Workload Cache Fix (NEW-001)
- Added cache invalidation to all task endpoints:
  - create_task, update_task, update_task_status
  - delete_task, restore_task, assign_task
- Extended to clear heatmap cache as well

## OpenSpec Archive
- 2026-01-05-add-kanban-realtime-sync

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 20:28:42 +08:00

3.9 KiB
Raw Blame History

Collaboration - Spec Delta

ADDED Requirements

Requirement: Project Real-time Sync

系統 SHALL 提供專案級即時同步機制,讓多位使用者同時協作時能即時看到任務變更。

Scenario: 訂閱專案即時更新

  • GIVEN 使用者擁有專案的存取權限
  • WHEN 使用者進入專案看板頁面
  • THEN 系統自動建立 WebSocket 連線並訂閱該專案的即時更新
  • AND 連線使用 JWT Token 進行身份驗證

Scenario: 接收任務狀態變更

  • GIVEN 使用者已訂閱專案即時更新
  • WHEN 其他使用者在同一專案中變更任務狀態
  • THEN 系統透過 WebSocket 即時推送 task_status_changed 事件
  • AND 看板 UI 自動更新任務位置

Scenario: 接收任務建立事件

  • GIVEN 使用者已訂閱專案即時更新
  • WHEN 其他使用者在同一專案中建立新任務
  • THEN 系統透過 WebSocket 即時推送 task_created 事件
  • AND 看板 UI 自動顯示新任務

Scenario: 接收任務刪除事件

  • GIVEN 使用者已訂閱專案即時更新
  • WHEN 其他使用者在同一專案中刪除任務
  • THEN 系統透過 WebSocket 即時推送 task_deleted 事件
  • AND 看板 UI 自動移除該任務

Scenario: 取消訂閱專案

  • GIVEN 使用者已訂閱專案即時更新
  • WHEN 使用者離開專案看板頁面
  • THEN 系統自動關閉 WebSocket 連線並取消訂閱
  • AND 釋放相關資源

Scenario: 樂觀更新與衝突處理

  • GIVEN 使用者拖曳任務改變狀態
  • WHEN 本地先套用變更(樂觀更新)但 API 呼叫失敗
  • THEN 系統回滾任務到原本位置
  • AND 顯示錯誤訊息通知使用者

Scenario: 避免重複應用自己的事件

  • GIVEN 使用者變更任務狀態並收到自己發起的事件
  • WHEN WebSocket 收到該事件
  • THEN 系統識別為本地發起的變更
  • AND 不重複應用該變更

MODIFIED Requirements

Requirement: Real-time Notifications

系統 SHALL 透過 Redis 推播即時通知。

Scenario: 即時通知推播

  • GIVEN 發生需要通知的事件(如:被指派任務、被 @提及、阻礙標記)
  • WHEN 事件發生
  • THEN 系統透過 WebSocket 即時推播通知給相關使用者
  • AND 未讀通知顯示數量標示

Scenario: 通知已讀標記

  • GIVEN 使用者有未讀通知
  • WHEN 使用者查看通知
  • THEN 系統標記為已讀
  • AND 更新未讀數量

Scenario: 專案事件頻道分離

  • GIVEN 系統運作中
  • WHEN 發生任務變更事件
  • THEN 通知系統使用 notifications:{user_id} 頻道推送個人通知
  • AND 即時同步系統使用 project:{project_id}:tasks 頻道推送專案事件
  • AND 兩者互不干擾

Technical Notes

WebSocket 端點

  • 通知端點: GET /ws/notifications?token=<jwt>
  • 專案同步端點: GET /ws/projects/{project_id}?token=<jwt>

Redis Pub/Sub Channels

  • 通知頻道: notifications:{user_id} (現有實作)
  • 專案任務事件頻道: project:{project_id}:tasks (新增)

事件訊息格式

{
  "type": "task_created | task_updated | task_status_changed | task_deleted | task_assigned",
  "event_id": "uuid",
  "data": {
    "task_id": "uuid",
    "project_id": "uuid",
    "title": "string",
    "status_id": "uuid | null",
    "status_name": "string | null",
    "status_color": "string | null",
    "assignee_id": "uuid | null",
    "time_estimate": "number | null",
    /* 其他任務欄位 */
  },
  "triggered_by": "user_id",
  "timestamp": "ISO8601"
}

欄位說明:

  • event_id: 唯一事件識別碼,用於多分頁/多裝置事件去重
  • triggered_by: 觸發事件的使用者 ID位於頂層便於前端過濾

連線管理

  • 使用與通知系統相同的心跳機制 (PING/PONG)
  • 支援同一使用者多個連線 (多分頁/裝置)
  • 連線中斷自動重連 (Frontend 實作)