feat(collector): brain event 중계 추가 — Watcher 이벤트를 Gateway로 전달

- collector.py: _forward_events_loop — BrainEvent를 JSON으로 serialize하여 /api/event POST
- gateway.py: /api/event 엔드포인트 — 수신한 이벤트를 bot event_queue에 주입
- main.py: event_queue를 CollectorBridge에 전달

이제 task.md, implementation_plan, walkthrough 변경사항이 Collector→Gateway→Discord 경로로 전달됨
This commit is contained in:
Variet Worker
2026-03-11 22:24:48 +09:00
parent 7e36db5191
commit 3d75825bba
3 changed files with 67 additions and 4 deletions

View File

@@ -18,6 +18,7 @@ from pathlib import Path
from bridge import LocalTransport, RemoteTransport
from config import Config
from watcher import BrainEvent, EventType
logger = logging.getLogger(__name__)
@@ -31,10 +32,12 @@ class CollectorBridge:
3. Polls Gateway for commands → writes to local commands/
"""
def __init__(self, local: LocalTransport, remote: RemoteTransport, project_name: str):
def __init__(self, local: LocalTransport, remote: RemoteTransport,
project_name: str, event_queue: asyncio.Queue | None = None):
self.local = local
self.remote = remote
self.project_name = project_name
self.event_queue = event_queue
self._forwarded_pending: set[str] = set() # already forwarded request IDs
self._poll_interval = 3 # seconds
self._running = False
@@ -43,11 +46,14 @@ class CollectorBridge:
"""Start the Collector polling loops."""
self._running = True
logger.info(f"[COLLECTOR] started for project={self.project_name}")
await asyncio.gather(
tasks = [
self._forward_pending_loop(),
self._poll_responses_loop(),
self._poll_commands_loop(),
)
]
if self.event_queue:
tasks.append(self._forward_events_loop())
await asyncio.gather(*tasks)
async def stop(self):
"""Stop the Collector."""
@@ -125,3 +131,28 @@ class CollectorBridge:
logger.error(f"[COLLECTOR] poll_commands error: {e}")
await asyncio.sleep(self._poll_interval)
# ─── Forward brain events → Gateway ───
async def _forward_events_loop(self):
"""Read BrainEvents from Watcher queue and POST to Gateway."""
while self._running:
try:
event: BrainEvent = await asyncio.wait_for(
self.event_queue.get(), timeout=5.0
)
# Serialize event to JSON
event_data = {
"event_type": event.event_type.value,
"conversation_id": event.conversation_id,
"file_name": event.file_name,
"file_path": str(event.file_path) if event.file_path else "",
"content": event.content,
"timestamp": event.timestamp,
}
self.remote._request("POST", "/api/event", event_data)
logger.info(f"[COLLECTOR] → Gateway: event {event.event_type.value} {event.file_name}")
except asyncio.TimeoutError:
continue
except Exception as e:
logger.error(f"[COLLECTOR] forward_event error: {e}")