Skip to content

fix(server): reconcile blocking result with TaskStore#991

Open
jstar0 wants to merge 4 commits into
a2aproject:mainfrom
jstar0:fix/2049-blocking-task-reconciliation
Open

fix(server): reconcile blocking result with TaskStore#991
jstar0 wants to merge 4 commits into
a2aproject:mainfrom
jstar0:fix/2049-blocking-task-reconciliation

Conversation

@jstar0

@jstar0 jstar0 commented Jul 23, 2026

Copy link
Copy Markdown

Summary

Fixes a race in the blocking Java server response path tracked by a2aproject/A2A#2049. onMessageSend can currently return an internal error when the agent is complete but TaskStore persistence is still becoming visible to the response aggregator.

Root Cause / Context

When the event consumer completes without delivering a Message or full Task event, ResultAggregator performs one TaskStore lookup and immediately raises Could not find a Task/Message if the row is not visible yet. That prevents the later response-handler TaskStore reconciliation from running.

Changes

  • Poll TaskStore with a bounded timeout when a blocking call has no in-memory result, while preserving the single-read behavior for non-blocking calls.
  • Make the reconciliation timeout configurable through a2a.blocking.reconciliation.timeout.seconds, retaining the existing one-second behavior by default.
  • Add debug logging for reconciliation attempts and successful delayed lookups.
  • Document the new setting and add regression coverage for delayed visibility, permanent absence, non-blocking behavior, configuration wiring, and the default property value.

Scope / Risk

Only the blocking empty-capture path polls TaskStore, and the default timeout remains one second. EventConsumer lifecycle, TaskStore APIs, cancellation, streaming emission, and the public A2A protocol are unchanged.

Verification

mvn -pl server-common test
mvn -pl integrations/microprofile-config test
mvn -pl server-common,integrations/microprofile-config -am -Dtest=ResultAggregatorTest,DefaultRequestHandlerTest,MicroProfileConfigProviderTest -Dsurefire.failIfNoSpecifiedTests=false test
git diff --check

The module suites pass 416 server-common tests and 10 MicroProfile config tests. The focused cross-module run passes 46 tests.

Fixes a2aproject/A2A#2049

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@kabir

kabir commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

@jstar0 Thank you! I've opened jstar0#1 with a few fixes to make the timeout configurable and some debug logging.

kabir and others added 2 commits July 23, 2026 20:27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Keep the existing four-argument constructor delegating to the original one-second reconciliation timeout, and cover the new configuration wiring and default value.

This fixes #2049
@jstar0

jstar0 commented Jul 23, 2026

Copy link
Copy Markdown
Author

Thanks @kabir. I integrated your configurable timeout and debug logging commit, then added coverage for the configuration wiring and default value. The focused 46-test run and the complete server-common (416) and MicroProfile config (10) suites pass.

@kabir kabir left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't se the need for the re-introduced constructor. Assuming I'm not mistaken, please get rid of it.
The additional tests look good though 👍

Comment thread server-common/src/main/java/org/a2aproject/sdk/server/tasks/ResultAggregator.java Outdated
@ehsavoie
ehsavoie requested a review from kabir July 23, 2026 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Blocking onMessageSend can throw "Could not find a Task/Message" even when TaskStore already has the completed Task

3 participants