ArcpClient.onError only completes sessionFuture exceptionally, and onComplete only fails the handshake future before welcome, as shown in arcp-client/src/main/java/dev/arcp/client/ArcpClient.java around lines 249 and 255. Futures in pendingSubmits, outstanding result futures, listRequests, and live subscription publishers are left open. A caller blocked in submit at line 152 or waiting on a JobHandle.result() can wait forever after the underlying transport fails.
Fix prompt: Add a single failAll(Throwable) path in ArcpClient that is called from onError, unexpected onComplete, heartbeat-loss close, and close failures where appropriate. It should complete sessionFuture, every pending submit handle future, every outstanding result future, every listJobs future, and every live subscription publisher exceptionally, then clear the corresponding maps. Preserve normal close behavior for successful terminal jobs, and add tests where the transport closes before job.accepted, after job.accepted but before job.result, and while listJobs is waiting.
ArcpClient.onError only completes sessionFuture exceptionally, and onComplete only fails the handshake future before welcome, as shown in arcp-client/src/main/java/dev/arcp/client/ArcpClient.java around lines 249 and 255. Futures in pendingSubmits, outstanding result futures, listRequests, and live subscription publishers are left open. A caller blocked in submit at line 152 or waiting on a JobHandle.result() can wait forever after the underlying transport fails.
Fix prompt: Add a single failAll(Throwable) path in ArcpClient that is called from onError, unexpected onComplete, heartbeat-loss close, and close failures where appropriate. It should complete sessionFuture, every pending submit handle future, every outstanding result future, every listJobs future, and every live subscription publisher exceptionally, then clear the corresponding maps. Preserve normal close behavior for successful terminal jobs, and add tests where the transport closes before job.accepted, after job.accepted but before job.result, and while listJobs is waiting.