Communication¶
All inter-service communication in Orion flows through Redis pub/sub. Services never make direct HTTP calls to each other.
Event Bus¶
The EventBus class in libs/orion-common/ provides an async Redis pub/sub wrapper:
from orion_common.event_bus import EventBus
bus = EventBus("redis://localhost:6379")
# Subscribe to events
await bus.subscribe("orion.trend.detected", handle_trend)
# Start background listener
await bus.start_listening()
# Publish an event
await bus.publish("orion.trend.detected", {
"trend_id": "abc-123",
"topic": "AI agents",
"source": "google_trends",
"score": 0.87,
"niche": "technology",
})
Channel Map¶
graph LR
SC["Scout"] -->|"orion.trend.detected"| DR["Director"]
SC -->|"orion.trend.detected"| PL["Pulse"]
SC -->|"orion.trend.expired"| PL
DR -->|"orion.content.created"| MD["Media"]
DR -->|"orion.content.created"| ED["Editor"]
DR -->|"orion.content.updated"| PL
DR -->|"orion.pipeline.stage_changed"| PL
MD -->|"orion.media.generated"| ED
MD -->|"orion.media.generated"| PL
MD -->|"orion.media.failed"| PL
PB["Publisher"] -->|"orion.content.published"| PL
API["CLI / API"] -->|"orion.content.rejected"| DR
Channel Reference¶
| Channel | Publisher | Subscribers | Payload |
|---|---|---|---|
orion.trend.detected |
Scout | Director, Pulse | {trend_id, topic, source, score, niche} |
orion.trend.expired |
Scout | Pulse | {trend_id} |
orion.content.created |
Director | Media, Editor | {content_id, trend_id, title, visual_prompts} |
orion.content.updated |
Director | Pulse | {content_id, status, stage} |
orion.content.rejected |
CLI/API | Director | {content_id, feedback, action} |
orion.content.published |
Publisher | Pulse | {content_id, platform, publish_id} |
orion.media.generated |
Media | Editor, Pulse | {content_id, asset_ids, provider} |
orion.media.failed |
Media | Pulse | {content_id, error} |
orion.pipeline.stage_changed |
Director | Pulse | {content_id, stage, timestamp} |
WebSocket Bridge¶
The gateway's WebSocket hub subscribes to Redis channels matching orion.* and broadcasts events to connected browser clients:
sequenceDiagram
participant Service
participant Redis
participant Gateway
participant Browser
Service->>Redis: PUBLISH orion.content.created {...}
Redis->>Gateway: Message on orion.*
Gateway->>Browser: WebSocket frame
- Endpoint:
GET /ws?token=<jwt> - Keepalive: Ping every 30 seconds
- Read timeout: 60 seconds
Event Guarantees¶
At-most-once delivery
Redis pub/sub provides at-most-once delivery. If a subscriber is offline when an event is published, the event is lost. For critical workflows, the Director uses LangGraph checkpointing to persist state and enable recovery.