fix: true parallel tool execution via subscribeOn(Schedulers.io()) in concatMapEager#1154
fix: true parallel tool execution via subscribeOn(Schedulers.io()) in concatMapEager#1154YuqiGuo105 wants to merge 1 commit intogoogle:mainfrom
Conversation
|
Hi @YuqiGuo105, Thank you for your contribution! We appreciate you taking the time to submit this pull request. I have noticed The Maven build is failing due to test case failures in this PR. Could you please address these failure? |
… concatMapEager Fixes google#1152
447c088 to
1db5e45
Compare
|
Hi @hemasekhar-p, the failed test case is fixed. ReasonEvery pre-existing test that failed involved exactly one tool call. When the parallel path (
Fixif (invocationContext.runConfig().toolExecutionMode() == ToolExecutionMode.SEQUENTIAL
|| validFunctionCalls.size() <= 1) {The Since parallel vs. sequential is meaningless for a single task, this is semantically correct and has no functional impact. |
Summary
Fixes #1152 —
ToolExecutionMode.PARALLELwas silently executing tools serially. Adding.subscribeOn(Schedulers.io())insideconcatMapEagerdispatches each tool's full pipeline to an IO thread, enabling true concurrent execution.Root Cause & Fix
Without
subscribeOn, all subscriptions run on the calling thread. Blocking tools hold that thread, preventing the next subscription from starting.Applied identically in both
handleFunctionCallsandhandleFunctionCallsLive.Execution Workflow
Before — serial on calling thread
After — concurrent on IO thread pool
concatMapEagerguarantees results are emitted in input order despite concurrent execution.Tests
All 26 tests pass (
Tests run: 26, Failures: 0, Errors: 0). 12 new tests added:handleFunctionCalls_parallelMode_runsToolsConcurrentlySlowTool×2 @ 500 msPARALLELhandleFunctionCalls_parallelMode_preservesInputOrderSlowToolslow(500ms), fast(100ms)PARALLELhandleFunctionCalls_noneModeDefaultsToParallel_runsToolsConcurrentlySlowTool×2 @ 500 msNONEhandleFunctionCalls_sequentialMode_runsToolsSeriallySlowTool×2 @ 300 msSEQUENTIALhandleFunctionCallsLive_parallelMode_runsToolsConcurrentlySlowTool×2 @ 500 msPARALLEL(Live path)handleFunctionCalls_parallelMode_threeTools_allStartConcurrentlySlowTool×3 @ 500 msPARALLELhandleFunctionCalls_blockingTools_parallel_executesInParallelBlockingTool×3 @ 1000 msPARALLELhandleFunctionCalls_blockingTools_defaultNoneMode_executesInParallelBlockingTool×2 @ 1000 msNONEhandleFunctionCalls_blockingTools_sequential_executesSeriallyBlockingTool×2 @ 500 msSEQUENTIALhandleFunctionCalls_blockingTools_parallel_preservesOrderBlockingToolslow(800ms), fast(100ms)PARALLELhandleFunctionCalls_blockingTools_parallel_usesMultipleThreadsBlockingTool×2 @ 500 msPARALLELhandleFunctionCalls_nonBlockingTools_parallel_stillWorksCorrectlyEchoTool×3PARALLEL