zmuxuny opened a new issue, #7152:
URL: https://github.com/apache/rocketmq-dashboard/issues/7152

   ### Before Creating the Bug Report
   
   - [x] I have searched the [open 
issues](https://github.com/apache/rocketmq-dashboard/issues) of this repository 
and believe that this is not a duplicate.
   
   - [x] This is a defect in RocketMQ Studio, not a usage question and not a 
defect in another Apache RocketMQ repository.
   
   - [x] I can reproduce this on the current `master` branch, or I have stated 
the exact version I am running below.
   
   
   ### Studio Version
   
   rocketmq-studio at 127c47b06a268cc74224d5f34c56ec7c36ac0d55.
   
   ### Runtime Environment
   
   Java 21.0.12.1, Maven 3.9.12, existing JUnit/Mockito tests. Reproduction 
runs the real AiRunService and registry with controlled repository query 
interleavings and deferred workers.
   
   ### Connected RocketMQ Cluster
   
   No live RocketMQ or provider needed. The invariant fails during admission, 
before agent work. The test models the existing UNIQUE(conversation_id, turn) 
constraint at the repository boundary; no live MySQL concurrency test is 
claimed.
   
   ### Build Toolchain
   
   Offline Maven using cached dependencies; Maven heap384MiB, test fork256MiB, 
one fork.
   
   ### Describe the Bug
   
   AiRunService.sendMessage checks for an active run before reading maxTurn. If 
one request's empty active lookup becomes stale while another request admits 
turn1, the delayed request then reads maxTurn1 and admits turn2. The existing 
unique turn key does not collide, so two QUEUED runs and live handles can own 
the same conversation. Each creates its own event sink despite the documented 
single-writer timeline assumption.
   
   ### Steps to Reproduce
   
   1. Start request A and retain its empty findActiveByConversationId result.
   2. Before returning that result to A, admit request B completely, leaving 
its worker queued.
   3. Resume A. It reads the now-increased maxTurn, chooses the next distinct 
turn, and inserts successfully.
   4. Inspect inserted rows: both turn1 and turn2 are QUEUED for the same 
conversation. The deterministic test invokes both real admission paths, models 
exact turn-key uniqueness and leaves workers deferred.
   
   ### What Did You Expect to See?
   
   Only one request is admitted while its run remains active; the other 
receives the existing409 busy refusal and does not persist a second user turn 
or register another worker.
   
   ### What Did You See Instead?
   
   The unchanged baseline fails with expected one active row, actual two QUEUED 
rows: IDs11/12, turns1/2. A second interleaving control, where both requests 
already chose the same turn before either insert, passes through the existing 
unique-key-to-409 handling. Result:2 tests,1 assertion failure,0 errors,1 
passing control.
   
   ### Additional Context
   
   A bounded correction is to read the candidate turn before checking active 
state. Seeing the winner's turn makes the subsequent active lookup refuse it; 
not seeing it makes both requests claim the same next turn, where the existing 
unique key rejects one. No new lock, API, schema or transaction is required. 
All-state searches found no equivalent fix; nearby #5755/#5761 concern 
terminal-state races, #5678 tests repository queries, and #6953/#6954 concern 
the separate deletion barrier. This report does not claim to fix concurrent 
conversation deletion.
   
   ### Are You Willing to Submit a Pull Request?
   
   - [x] Yes, I am willing to submit a pull request.


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