refactor: move runtime event publishing out of loop
This commit is contained in:
@@ -16,6 +16,8 @@ from typing import Any
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from nanobot.bus.events import InboundMessage
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RuntimeEventContext:
|
||||
@@ -129,3 +131,121 @@ class RuntimeEventBus:
|
||||
logger.debug("dropping runtime event without a running loop: {}", type(event).__name__)
|
||||
return
|
||||
loop.create_task(self.publish(event))
|
||||
|
||||
|
||||
class RuntimeEventPublisher:
|
||||
"""Convenience publisher for turn-scoped runtime events.
|
||||
|
||||
Agent code should decide when state transitions happen; this helper owns
|
||||
the mechanics of building event contexts and carrying per-turn metadata.
|
||||
"""
|
||||
|
||||
def __init__(self, bus: RuntimeEventBus | None = None) -> None:
|
||||
self.bus = bus or RuntimeEventBus()
|
||||
self._turn_latency_ms: dict[str, int] = {}
|
||||
self._turn_runtime: dict[str, Any] = {}
|
||||
|
||||
@staticmethod
|
||||
def _context(
|
||||
*,
|
||||
channel: str,
|
||||
chat_id: str,
|
||||
session_key: str,
|
||||
metadata: dict[str, Any] | None,
|
||||
) -> RuntimeEventContext:
|
||||
return RuntimeEventContext(
|
||||
channel=channel,
|
||||
chat_id=chat_id,
|
||||
session_key=session_key,
|
||||
metadata=dict(metadata or {}),
|
||||
)
|
||||
|
||||
def record_turn_runtime(self, session_key: str, runtime: Any) -> None:
|
||||
self._turn_runtime[session_key] = runtime
|
||||
|
||||
def record_turn_latency(self, session_key: str, latency_ms: int | None) -> None:
|
||||
if latency_ms is not None:
|
||||
self._turn_latency_ms[session_key] = int(latency_ms)
|
||||
|
||||
def clear_turn(self, session_key: str) -> None:
|
||||
self._turn_latency_ms.pop(session_key, None)
|
||||
self._turn_runtime.pop(session_key, None)
|
||||
|
||||
async def session_turn_started(
|
||||
self,
|
||||
msg: InboundMessage,
|
||||
session_key: str,
|
||||
) -> None:
|
||||
await self.bus.publish(
|
||||
SessionTurnStarted(
|
||||
context=self._context(
|
||||
channel=msg.channel,
|
||||
chat_id=msg.chat_id,
|
||||
session_key=session_key,
|
||||
metadata=msg.metadata,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
async def run_status_changed(
|
||||
self,
|
||||
msg: InboundMessage,
|
||||
session_key: str,
|
||||
status: str,
|
||||
*,
|
||||
started_at: float | None = None,
|
||||
) -> None:
|
||||
await self.bus.publish(
|
||||
TurnRunStatusChanged(
|
||||
context=self._context(
|
||||
channel=msg.channel,
|
||||
chat_id=msg.chat_id,
|
||||
session_key=session_key,
|
||||
metadata=msg.metadata,
|
||||
),
|
||||
status=status,
|
||||
started_at=started_at,
|
||||
)
|
||||
)
|
||||
|
||||
async def turn_completed(
|
||||
self,
|
||||
*,
|
||||
channel: str,
|
||||
chat_id: str,
|
||||
session_key: str,
|
||||
metadata: dict[str, Any] | None,
|
||||
) -> None:
|
||||
await self.bus.publish(
|
||||
TurnCompleted(
|
||||
context=self._context(
|
||||
channel=channel,
|
||||
chat_id=chat_id,
|
||||
session_key=session_key,
|
||||
metadata=metadata,
|
||||
),
|
||||
latency_ms=self._turn_latency_ms.pop(session_key, None),
|
||||
runtime=self._turn_runtime.pop(session_key, None),
|
||||
)
|
||||
)
|
||||
|
||||
def runtime_model_changed(self, model: str, model_preset: str | None) -> None:
|
||||
self.bus.publish_nowait(
|
||||
RuntimeModelChanged(model=model, model_preset=model_preset)
|
||||
)
|
||||
|
||||
|
||||
def ensure_runtime_event_publisher(owner: Any) -> RuntimeEventPublisher:
|
||||
"""Return an owner's runtime publisher, creating missing state lazily."""
|
||||
publisher = getattr(owner, "runtime_event_publisher", None)
|
||||
if isinstance(publisher, RuntimeEventPublisher):
|
||||
return publisher
|
||||
|
||||
bus = getattr(owner, "runtime_events", None)
|
||||
if not isinstance(bus, RuntimeEventBus):
|
||||
bus = RuntimeEventBus()
|
||||
owner.runtime_events = bus
|
||||
|
||||
publisher = RuntimeEventPublisher(bus)
|
||||
owner.runtime_event_publisher = publisher
|
||||
return publisher
|
||||
|
||||
Reference in New Issue
Block a user