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

   ### Studio Version
   branch: `rocketmq-studio` @ `6a68042f` (the revision verified; the branch is 
based on it)
   deployed as: built from source (unit test)
   
   ### Runtime Environment
   
   Not environment-specific: the run lifecycle, verified with unit tests.
   
   ### Connected RocketMQ Cluster
   
   Not cluster-specific (AI runs).
   
   ### Describe the Bug
   
   `AgentRunRegistry.stop` returns `false` both when no handle exists and when 
the handle's abort CAS was already decided (the javadoc says "false when the 
run was already aborted, in which case this call did nothing at all"). 
`AiRunService.stop` reads that single boolean as "nothing in this process owns 
it" and calls `runExecutor.terminate(detachedContext(run), STOPPED, USER_STOP, 
...)`, which builds a new context whose `beginTerminal()` CAS no worker holds: 
it appends a terminal `run_status` row at `MAX(seq)+1`, rewrites the run row 
and closes every observer. The first stop is still inside 
`AgentRunHandle.awaitStop` for the SIGTERM grace, so the worker's buffered 
final text then flushes into that same sequence, `AiEventSink.insert` rethrows 
`DuplicateKeyException` (logged and dropped), and the fabricated row wins.
   
   ### Steps to Reproduce
   
   1. Start a run and press Stop in one tab.
   2. Press Stop again from a second tab (or retry `POST 
/api/ai/runs/{id}/stop`) while the first stop is still within its grace period.
   3. Reload the conversation and observe a duplicate terminal marker / an 
empty 已停止 bubble; the answer's last chunk is missing.
   
   ### What Did You Expect to See?
   
   The second stop is a no-op and the worker writes the single terminal state, 
as the endpoint's idempotence promises.
   
   ### What Did You See Instead?
   
   A second terminal state is written by the service and the worker's flush 
collides with it.
   
   ### Evidence
   
   - `ops/ai/conversation/AgentRunRegistry.java` (`stop`), 
`AgentRunHandle.java` (`stop`/`requestStop`), `AiRunService.java` (the detached 
branch), `AiRunExecutor.java` (`terminate`), `AiEventSink.java` 
(DuplicateKeyException rethrow), `web/src/pages/ai/render/foldTimeline.ts` (the 
second `run_status` opens an empty bubble).
   - `cd server && mvn -o test 
-Dtest='org.apache.rocketmq.studio.ops.ai.conversation.*Test'` — the added case 
`secondStopOfAnAbortingRunShouldNotWriteItsOwnTerminalStateTest` fails before 
the change (the service writes a `run_status` row and a run update for a run 
whose worker is already stopping) and passes after (`Tests run: 202`).
   
   ### Impact
   
   A duplicated terminal row, a phantom empty bubble after a reload, and the 
loss of the run's last buffered output.
   
   ### Acceptance Criteria
   
   - A run this process is stopping is left to its worker; only an unowned 
non-terminal run gets the detached write.
   - A regression test pins that a second stop writes nothing.
   
   **Corresponding PR:** #5440
   


-- 
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