From 6394a6f56cae6af65b0af383e7e9acb3f1d6cdd7 Mon Sep 17 00:00:00 2001 From: Ivan Shymko Date: Fri, 15 May 2026 14:25:21 +0000 Subject: [PATCH] docs: clarify EventQueue usage Fixes #1064. --- src/a2a/server/events/event_queue.py | 47 +++++++++++----------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/src/a2a/server/events/event_queue.py b/src/a2a/server/events/event_queue.py index bb4d7b9b4..046dad291 100644 --- a/src/a2a/server/events/event_queue.py +++ b/src/a2a/server/events/event_queue.py @@ -1,6 +1,7 @@ import asyncio import logging import sys +import warnings from abc import ABC, abstractmethod from types import TracebackType @@ -48,38 +49,28 @@ def _create_async_queue(maxsize: int = 0) -> AsyncQueue[Any]: class EventQueue(ABC): - """Base class and factory for EventQueueSource. - - EventQueue provides an abstraction for a queue of events that can be tapped - by multiple consumers. - EventQueue maintain main queue and source and maintain child queues in sync. - GUARANTEE: All sinks (including the default one) will receive events in the exact same order. - - WARNING (Concurrency): All events from all sinks (both the default queue and any - tapped child queues) must be regularly consumed and marked as done. If any single - consumer stops processing and its queue reaches capacity, it can block the event - dispatcher and stall the entire system, causing a widespread deadlock. - - WARNING (Memory Leak): Event queues spawn background tasks. To prevent memory - and task leaks, all queue objects (both source and sinks) MUST be explicitly - closed via `await queue.close()` or by using the async context manager (`async with queue:`). - Child queues are automatically closed when parent queue is closed, but you - should still close them explicitly to prevent queues from reaching capacity by - unconsumed events. - - Typical usage: - queue = EventQueue() - child_queue1 = await queue.tap() - child_queue2 = await queue.tap() - - async for event in child_queue1: - do_some_work(event) - child_queue1.task_done() + """Producer-side interface passed to `AgentExecutor.execute`/`cancel`. + + Exposes only `enqueue_event`. The consumer is framework-managed + and not part of the public surface. + + Default request handlers construct the queue and pass it in; executors + should accept it and not construct one. To run an executor outside the + framework, write a custom subclass or use `EventQueueLegacy` (deprecated, + will be removed in a future release). """ def __new__(cls, *args: Any, **kwargs: Any) -> Self: - """Redirects instantiation to EventQueueLegacy for backwards compatibility.""" + """Deprecated: redirects bare `EventQueue(...)` to `EventQueueLegacy(...)`.""" if cls is EventQueue: + warnings.warn( + 'EventQueue is an abstract interface; instantiating it ' + 'directly is deprecated. The redirect to EventQueueLegacy ' + '(and EventQueueLegacy itself) will be removed in a future ' + 'release.', + DeprecationWarning, + stacklevel=2, + ) instance = EventQueueLegacy.__new__(EventQueueLegacy) EventQueueLegacy.__init__(instance, *args, **kwargs) return cast('Self', instance)