refactor(api): Sentry dedup 邏輯移至 Service 層 (leWOOOgo 模組化)

Phase 10.2.1 - 2026-03-27 台北時區
- 將 check_sentry_dedup() 從 Router 移至 SentryService.check_dedup()
- Router 層禁止直接存取 Redis (遵循 leWOOOgo 積木化原則)
- 保持 10 分鐘 TTL 去重窗口

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-03-27 15:04:53 +08:00
parent 54061fb8be
commit 2b069818af
2 changed files with 44 additions and 0 deletions

View File

@@ -196,6 +196,40 @@ class SentryService:
"""取得 Issue 在 Sentry UI 的連結"""
return f"{self.base_url}/organizations/{self.org}/issues/{issue_id}/"
# =========================================================================
# Dedup (Phase 10.2.1 - 2026-03-27)
# =========================================================================
async def check_dedup(self, issue_id: str, ttl: int = 600) -> bool:
"""
檢查 Sentry Issue 是否已在去重窗口內
Args:
issue_id: Sentry Issue ID
ttl: 去重窗口秒數 (預設 10 分鐘)
Returns:
bool: True = 應處理, False = 已去重跳過
"""
from src.core.redis_client import get_redis_pool
if not issue_id:
return True
redis = await get_redis_pool()
key = f"sentry_dedup:{issue_id}"
# 檢查是否已存在
exists = await redis.exists(key)
if exists:
logger.info("sentry_dedup_hit", issue_id=issue_id)
return False
# 設置去重標記
await redis.setex(key, ttl, "1")
logger.debug("sentry_dedup_set", issue_id=issue_id, ttl=ttl)
return True
# =============================================================================
# Singleton