feat(api): POST /api/v1/aider/events HMAC webhook + Redis stream push
- Router layer: HTTP validation + HMAC-SHA256 signature verification - Service layer: Redis stream push (aider_event_service.push_aider_batch_to_stream) - leWOOOgo積木化遵循: Router → Service → Redis - All 6 tests passing (signature validation, batch limits, edge cases)
This commit is contained in:
@@ -5,10 +5,12 @@
|
||||
- 不重做 dedup — 既有 IncidentService.create_incident_from_signal 已有 3min fingerprint debounce
|
||||
- 不做 pattern extract — Task A8 ai_router 會直接從 aider_event_repository 聚合
|
||||
- 純函式為主,副作用(建 incident)由 caller(A7 processor job)管理
|
||||
- Redis stream 推送 (Task A6):轉接 Router 層
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import os
|
||||
from typing import Any
|
||||
from src.models.aider import AiderEventIn
|
||||
from src.models.aider import AiderEventIn, AiderBatchIn
|
||||
from src.utils.secret_redactor import redact
|
||||
|
||||
|
||||
@@ -109,3 +111,25 @@ def _compact_desc(event_type: str, payload: dict) -> str:
|
||||
f"duration={payload.get('duration_sec',0)}s "
|
||||
f"tokens={payload.get('tokens_sent',0)}+{payload.get('tokens_received',0)}")
|
||||
return str(payload)[:200]
|
||||
|
||||
|
||||
# ---- Redis stream 推送 (Task A6) ----
|
||||
|
||||
async def push_aider_batch_to_stream(batch: AiderBatchIn) -> list[str]:
|
||||
"""把 event batch 推到 Redis stream。回傳 stream ID 列表。"""
|
||||
from src.core.redis_client import get_redis
|
||||
|
||||
stream_key = os.environ.get("AIDER_EVENTS_STREAM_KEY", "signals:aider:events")
|
||||
r = get_redis()
|
||||
|
||||
ids = []
|
||||
for ev in batch.events:
|
||||
msg_id = await r.xadd(stream_key, {"payload": ev.model_dump_json()})
|
||||
ids.append(_to_str(msg_id))
|
||||
|
||||
return ids
|
||||
|
||||
|
||||
def _to_str(x) -> str:
|
||||
"""轉成 str(相容 bytes 和 str 回傳值)。"""
|
||||
return x.decode() if isinstance(x, bytes) else str(x)
|
||||
|
||||
Reference in New Issue
Block a user