Task 11: cluster protocol — subscribe(), ping/pong health, 9 message types
- amqp.py: subscribe() creates exclusive queues bound to routing keys, _rebind_subscriptions() recreates them after reconnect - cluster.py: CLUSTER_NODES, CLUSTER_EVENTS (bounded 1000), CLUSTER_COORDINATOR with auto-promotion, all 6 handlers (register, deregister, pong, event, coordinator_query), ping_node() with 5s timeout + auto-deregister on failure - routers/cluster.py: GET /api/cluster - Wired into app.py lifespan after amqp_connect() - 13 tests covering all handlers, boundaries, and API shape - No passive heartbeats — workers assumed present until ping timeout at work-routing time
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
"""JarvisChat routers - Cluster status API."""
|
||||
from fastapi import APIRouter
|
||||
|
||||
import cluster
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/api/cluster")
|
||||
async def cluster_status():
|
||||
return {
|
||||
"nodes": {name: _strip_internal(node) for name, node in cluster.CLUSTER_NODES.items()},
|
||||
"node_count": len(cluster.CLUSTER_NODES),
|
||||
"coordinator": cluster.CLUSTER_COORDINATOR,
|
||||
"events": list(cluster.CLUSTER_EVENTS),
|
||||
}
|
||||
|
||||
|
||||
def _strip_internal(node: dict) -> dict:
|
||||
return {k: v for k, v in node.items() if k in {
|
||||
"name", "type", "status", "capabilities", "active_model", "load",
|
||||
"registered_at", "last_seen",
|
||||
}}
|
||||
Reference in New Issue
Block a user