Commit d3f88cb
authored
fix: resolve event stream race conditions in EventConsumer and SSE tr… (#782)
…ansport
Fixed multiple race conditions causing intermittent test failures in
streaming and subscription scenarios. These fixes reduced the failure
rate from ~33% to 0% across 1,500+ test iterations in CI.
Removed executor.execute() wrapper in REST/JSONRPC routes that delayed
subscription by 100-600ms, causing events to be lost when EventConsumer
started emitting before subscriber was ready.
Changed onCancelTask to use consumeAndBreakOnInterrupt() instead of
consumeAll(). Removed unused ResultAggregator.consumeAll() method since
cancel was its only caller.
Moved EventConsumer polling loop to executor thread to prevent blocking
caller, ensuring subscription happens immediately without delay.
Fixed race in onSubscribeToTask where initial task snapshot was enqueued
but EventConsumer polling hadn't started yet. Added insertingProcessor()
utility to AsyncUtils that prepends initial items synchronously to
reactive streams using mutiny-zero ZeroPublisher, ensuring subscriber
receives initial task snapshot immediately on subscription.
Updated transport layer unit tests (JSONRPCHandlerTest, GrpcHandlerTest)
to expect initial task snapshot per A2A Protocol Specification 3.1.6.
Fixed insertingProcessor() to respect reactive streams semantics by
sending inserted items in the source's onSubscribe() callback after
subscription is established, rather than immediately in the
ZeroPublisher creation lambda.
Fixed two test race conditions where tests checked for received events
immediately after subscription was established (server-side metric),
without waiting for consumer callbacks to actually process events:
- testSubscribeToTaskWithInterruptedStateKeepsStreamOpen: Added
initialTaskLatch to wait for initial TaskEvent reception
- testNonBlockingWithMultipleMessages: Added streamConsumerReadyLatch to
wait for streaming consumer to start receiving events
Enhanced awaitingFinalEvent tracking with timeout guards (max 3s wait)
to prevent infinite waiting if final event never arrives due to
distribution delays in replicated scenarios.
Increased sleep delay from 50ms to 150ms to account for CI environment
latency and ensure buffered events flush before stream ends.
Improved pollTimeoutsWhileAwaitingFinal reset logic to only reset when
not awaiting final event. Calculated timeout constant from base timeout
value for better maintainability.
Tests fixed:
- testNonBlockingWithMultipleMessages
- testCancelTaskSuccess
- testSubscribeToTaskWithInterruptedStateKeepsStreamOpen1 parent c12888d commit d3f88cb
12 files changed
Lines changed: 422 additions & 257 deletions
File tree
- reference
- jsonrpc/src/main/java/io/a2a/server/apps/quarkus
- rest/src/main/java/io/a2a/server/rest/quarkus
- server-common/src
- main/java/io/a2a/server
- events
- requesthandlers
- tasks
- util/async
- test/java/io/a2a/server
- events
- tasks
- tests/server-common/src/test/java/io/a2a/server/apps/common
- transport
- grpc/src/test/java/io/a2a/transport/grpc/handler
- jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler
Lines changed: 19 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
299 | 299 | | |
300 | 300 | | |
301 | 301 | | |
302 | | - | |
303 | | - | |
304 | | - | |
305 | | - | |
306 | | - | |
307 | | - | |
308 | | - | |
309 | | - | |
310 | | - | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
311 | 311 | | |
312 | 312 | | |
313 | 313 | | |
| |||
783 | 783 | | |
784 | 784 | | |
785 | 785 | | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
786 | 789 | | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
787 | 797 | | |
788 | 798 | | |
789 | 799 | | |
| |||
Lines changed: 18 additions & 18 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
221 | 221 | | |
222 | 222 | | |
223 | 223 | | |
224 | | - | |
225 | | - | |
226 | | - | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
233 | 233 | | |
234 | 234 | | |
235 | 235 | | |
| |||
431 | 431 | | |
432 | 432 | | |
433 | 433 | | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | | - | |
438 | | - | |
439 | | - | |
440 | | - | |
441 | | - | |
442 | | - | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
443 | 443 | | |
444 | 444 | | |
445 | 445 | | |
| |||
0 commit comments