diff --git a/agent-office/app/node_monitor.py b/agent-office/app/node_monitor.py index e88a2c6..5dec02d 100644 --- a/agent-office/app/node_monitor.py +++ b/agent-office/app/node_monitor.py @@ -14,8 +14,9 @@ WORKER_REGISTRY = [ {"name": "video-render", "kind": "render", "queue": "queue:video-render"}, {"name": "image-render", "kind": "render", "queue": "queue:image-render"}, {"name": "insta-render", "kind": "render", "queue": "queue:insta-render"}, - {"name": "task-watcher", "kind": "watcher", "queue": None}, - {"name": "ai_trade", "kind": "trader", "queue": None}, + {"name": "task-watcher", "kind": "watcher", "queue": None}, + {"name": "ai_trade", "kind": "trader", "queue": None}, + {"name": "trade-monitor", "kind": "trader", "queue": None}, ] _redis = None @@ -92,7 +93,7 @@ async def collect_status(redis=None) -> dict: for w in out["workers"]: if w["kind"] == "trader": - out["links"].append({"from": "ai_trade", "to": "nas-stock", "type": "http-pull", + out["links"].append({"from": w["name"], "to": "nas-stock", "type": "http-pull", "status": "healthy" if w["alive"] else "down"}) elif w["kind"] == "render": out["links"].append({"from": "nas", "to": w["name"], "type": "redis-queue", diff --git a/agent-office/tests/test_node_monitor.py b/agent-office/tests/test_node_monitor.py index 5df84af..ca6249a 100644 --- a/agent-office/tests/test_node_monitor.py +++ b/agent-office/tests/test_node_monitor.py @@ -68,6 +68,18 @@ async def test_trader_http_pull_link(): link = next(l for l in st["links"] if l["from"] == "ai_trade") assert link["type"] == "http-pull" and link["status"] == "healthy" +@pytest.mark.asyncio +async def test_trade_monitor_registered_and_own_link(): + """WSL 워커 trade-monitor가 registry에 있어 /nodes에 노출되고, 링크 from은 + ai_trade 하드코딩이 아니라 자기 이름(trade-monitor)이어야 한다 (다중 trader 구분).""" + r = FakeRedis(kv={"worker:trade-monitor:heartbeat": _hb("trade-monitor", "trader", "market_open")}) + st = await node_monitor.collect_status(redis=r) + tm = next(w for w in st["workers"] if w["name"] == "trade-monitor") + assert tm["alive"] is True and tm["kind"] == "trader" + link = next(l for l in st["links"] if l["from"] == "trade-monitor") + assert link["type"] == "http-pull" and link["to"] == "nas-stock" and link["status"] == "healthy" + + @pytest.mark.asyncio async def test_paused_no_watcher_heartbeat_fallback_reason(): """paused=True인데 watcher heartbeat 없으면 paused_reason == 'trading' 폴백."""