(feat) : implement cancellation support with CancellationToken and CancellationTokenSource - #1434
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
Hi @rohan-naik07, thank you for your contribution! We appreciate you taking the time to submit this pull request. To proceed with the review, could you please address the following,
|
ccb12a5 to
48953d7
Compare
48953d7 to
97dc77e
Compare
|
@rohan-naik07 Thank you for completing the Google CLA and squashing your changes into a single commit. However, I noticed that the Maven build is still failing. Could you please investigate and resolve these remaining build issues? |
97dc77e to
b00910e
Compare
…llationTokenSource
b00910e to
ff6d927
Compare
|
Thank you for addressing those comments @rohan-naik07. This PR is currently under review by our team and we will reach out if we require any further information. Thank you! |
Link to Issue or Description of Change
Related issue: #1341
Problem:
Java ADK does not provide an invocation-wide cancellation mechanism. Disposing the returned
RxJava subscription only controls that subscription and cannot be inspected consistently by nested
agents, model flows, tools, or callbacks. As a result, applications cannot implement graceful Stop
buttons or propagate request deadlines through an agent invocation.
Solution:
Add explicit, cooperative cancellation through
CancellationTokenandCancellationTokenSource:The token is stored in
RunConfigand shared throughInvocationContext, so the same signal isvisible throughout the invocation, including nested agents.
CancellationToken.none()preservesthe existing behavior when callers do not configure cancellation.
CancellationTokenSourceusesatomic state, making
cancel()thread-safe and idempotent.Cancellation checkpoints cover:
runAsyncandrunLiveexecution.Cancellation is graceful: the event stream completes normally, without an error or a synthetic
cancelled event. Events emitted before cancellation remain available to the caller and can still be
persisted. An already-running atomic model or tool operation may finish before the following
checkpoint. When a live receive flow terminates, its send task is disposed and its model connection
is closed.
RxJava disposal remains complementary and continues to cancel disposable upstream operations. It
is not used as the invocation-wide public cancellation contract.
Testing Plan
Unit Tests:
RunConfig.builder(existingConfig).close()behavior.event and prevents tool execution.
Focused test command:
./mvnw -pl core \ -Dtest=CancellationTokenSourceTest,RunConfigTest,BaseLlmFlowTest testResult: 42 tests run, 0 failures, 0 errors.
Compilation also succeeds:
The required
./mvnw testcommand was also run. It currently reports unrelated failures in thecheckout, including
NoSuchElementExceptionfrom the pre-existingLlmAgent.maybeSaveOutputToState()implementation. The cancellation-focused tests pass in bothconfigured Surefire executions.
Manual End-to-End (E2E) Tests:
Not run. The behavior is covered at the model and tool execution boundaries with deterministic unit
tests.
Checklist
Additional context
The API follows the explicit token/source pattern used by other structured cancellation systems
while retaining RxJava as the execution mechanism. It also aligns with TypeScript ADK's documented
graceful, cooperative, and idempotent cancellation semantics.
No cancellation event is written into conversation history. Cancellation represents invocation
lifecycle metadata rather than model-visible conversation content; applications that need to show
a cancelled status can derive it from the token they own.