unbridled-41 opened a new issue, #4795:
URL: https://github.com/apache/rocketmq-dashboard/issues/4795

   ### Studio Version
   
   Trunk `rocketmq-studio` @ `4c697f07` (line references are as of that commit).
   
   ### Problem
   
   `AiRunService.sendMessage` 
(`server/src/main/java/org/apache/rocketmq/studio/ops/ai/conversation/AiRunService.java:202`)
 inserts the run row (status `QUEUED`) and **then** calls 
`workspace.prepare(...)` at `AiRunService.java:207-208`, outside any try/catch. 
`RmqctlWorkspace.prepare` (`agent/RmqctlWorkspace.java:221-227`) deliberately 
throws `BusinessException` for three configuration conditions — an unusable 
`rmqctl-server-url`, an unusable `workspace-dir`, or an instance whose 
credential cannot be resolved (e.g. the bound instance was deleted, or its 
admin/cloud credential removed after the conversation was created; 
`InstanceCredentialResolver.resolveByName` throws 404/422).
   
   When it throws, the SSE stream refuses with the error, but the 
already-inserted run row is never registered, never finalized, and stays 
`QUEUED`. Admission is one-active-run-per-conversation 
(`findActiveByConversationId` at `AiRunService.java:191-195`), so **every 
subsequent message for that conversation is refused 409 "answer in progress"**. 
The only recovery is the orphan sweep in `purgeExpired` — 
`@Scheduled(fixedDelayString = 
"${studio.ai.conversation.cleanup-interval:PT24H}")` with a 10-minute 
`orphanRunTimeout` grace — i.e. up to 24 hours, or a server restart.
   
   ### Evidence
   
   1. `prepare()` javadoc promises "these fail loudly": `@throws 
BusinessException when the workspace could be built but the configuration is 
wrong: an unusable rmqctl-server-url, an unusable workspace-dir, or an instance 
with no resolvable credential` (`RmqctlWorkspace.java:221-227`).
   2. `insertRun` at `AiRunService.java:202` runs first; nothing between it and 
the throw writes a terminal state. `registry.register` (`:217`) never runs, so 
the row has no live handle and is invisible to the stop path's fast recovery.
   3. Measured on trunk source in this sandbox: a test stubbing `prepare` to 
throw 404 shows `sendMessage` propagating the exception with the row still 
`QUEUED` and zero terminal updates — then, with the fix, the row reaches 
`FAILED` before the exception is rethrown.
   
   ### Impact
   
   A user whose conversation references a deleted or de-credentialed instance 
cannot send any message for the rest of the day: every send returns 409 "busy" 
while the conversation shows a stranded QUEUED run. The timeline never records 
what happened, and the operator's only signal is a log line from the scheduled 
sweep a day later.
   
   ### Expected behavior
   
   An admission-time preparation failure must finalize the inserted row 
(through the same exactly-once terminal path the stop of an owner-less run 
uses) and still propagate the error to the caller.
   
   ### Related work
   
   - #4754 (mine, merged): retention deleting conversation rows but not disk 
workspaces — same subsystem, different lifecycle defect.
   - #4685 (open): resuming a CLI session the provider lost — also 
run-lifecycle, but about resume, not admission ordering.
   - #4740 (open): refused send and the composer draft — the client side of the 
same 409 refusal path.
   
   ## PR
   
   Fix: #… (opened together with this issue).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to