simple event bus impl

This commit is contained in:
lda
2026-05-12 19:43:02 +07:00 Verified
parent 8235794c58
commit bead0aadfd
10 changed files with 214 additions and 45 deletions
+10
View File
@@ -0,0 +1,10 @@
from .bus import EventBus, EventSubscriber, InMemoryEventSink
from .models import McpEvent, make_event
__all__ = [
"EventBus",
"EventSubscriber",
"InMemoryEventSink",
"McpEvent",
"make_event",
]
+44
View File
@@ -0,0 +1,44 @@
from __future__ import annotations
from collections.abc import Callable
from .models import McpEvent
EventSubscriber = Callable[[McpEvent], None]
class InMemoryEventSink:
"""Append-only event sink used by current broker history APIs."""
def __init__(self) -> None:
self._events: list[McpEvent] = []
def __call__(self, event: McpEvent) -> None:
self._events.append(event)
def list_events(self) -> list[McpEvent]:
"""Return a defensive copy of recorded events."""
return list(self._events)
class EventBus:
"""Synchronous in-process fanout for broker-local events.
This is intentionally not an MCP notification system. Protocol projections
can subscribe later without changing service code that emits events.
"""
def __init__(self, history: InMemoryEventSink | None = None) -> None:
self._history = history or InMemoryEventSink()
self._subscribers: list[EventSubscriber] = [self._history]
def subscribe(self, subscriber: EventSubscriber) -> None:
self._subscribers.append(subscriber)
def publish(self, event: McpEvent) -> None:
for subscriber in self._subscribers:
subscriber(event)
def list_events(self) -> list[McpEvent]:
"""Expose the default history sink for compatibility tools/resources."""
return self._history.list_events()
+36
View File
@@ -0,0 +1,36 @@
from __future__ import annotations
import time
from dataclasses import dataclass, field
from typing import Any
@dataclass(slots=True)
class McpEvent:
"""Broker-local event record before protocol-specific projection."""
kind: str
timestamp_epoch_ms: int
connection_id: str | None = None
capability_id: str | None = None
workflow_name: str | None = None
payload: dict[str, Any] = field(default_factory=dict)
def make_event(
kind: str,
*,
connection_id: str | None = None,
capability_id: str | None = None,
workflow_name: str | None = None,
payload: dict[str, Any] | None = None,
) -> McpEvent:
"""Create a timestamped event with optional routing metadata."""
return McpEvent(
kind=kind,
timestamp_epoch_ms=int(time.time() * 1000),
connection_id=connection_id,
capability_id=capability_id,
workflow_name=workflow_name,
payload=payload or {},
)