Fix a critical concurrency bug in A2aEventQueue.publish() where the method
iterates over _subscriptions without holding a lock. This causes RuntimeError:
dictionary changed size during iteration when subscribe_local/unsubscribe are
called concurrently from other threads.
The fix introduces a threading.Lock to protect all state mutations and
dictionary access in the A2aEventQueue class, while carefully ensuring callbacks
are invoked outside the lock to prevent potential deadlocks.
Changes:
- src/cleveragents/a2a/events.py: Added _lock attribute, protected
__init__, is_closed, publish, subscribe_local, unsubscribe, get_events,
and close methods with threading.Lock snapshot pattern for callbacks.
- features/a2a_event_queue_concurrency.feature: BDD feature file with 6
scenarios covering concurrent publish/subscribe/unsubscribe safety.
- features/steps/a2a_event_queue_concurrency_steps.py: Step definitions
implementing multi-threaded concurrency test harness.
ISSUES CLOSED: #7604