iloveeyjafjalla opened a new pull request, #6668:
URL: https://github.com/apache/rocketmq-dashboard/pull/6668

   ## Which Issue(s) This PR Fixes
   
   Fixes #6667
   
   ## Problem / Evidence
   
   `ResourceOwnershipGuard` reserves the topic/group row with a raw INSERT that 
names neither `gmt_create` nor `gmt_modified`, so both columns come from the 
schema default (`DEFAULT CURRENT_TIMESTAMP`) — the **database's** clock:
   
   ```java
   // before
   jdbc.update("INSERT INTO rmq_instance_topic (name, instance_id, cluster_id, 
status, topic_type)"
           + " VALUES (?, ?, ?, 'PENDING', ?)", ...);
   jdbc.update("INSERT INTO rmq_instance_group (name, instance_id, cluster_id, 
status)"
           + " VALUES (?, ?, ?, 'PENDING')", ...);
   ```
   
   The create path then re-reads the reserved row and only stamps the creation 
time when it created that row itself, while it stamps `gmt_modified` 
unconditionally:
   
   ```java
   // RocketMQAdminClientImpl:316-326
   boolean isNew = entity == null;                  // false - the guard 
reserved the row first
   if (isNew) { entity.setGmtCreate(LocalDateTime.now()); }
   entity.setGmtModified(LocalDateTime.now());      // studio clock
   ```
   
   On the running stack (the checkout default `serverTimezone=UTC` database, 
studio JVM in Asia/Shanghai) a topic created at local `22:26:44` therefore 
stored:
   
   ```
   id  name        gmt_create            gmt_modified
   31  tz-probe-1  2026-10-14 14:26:44   2026-10-14 22:26:45
   ```
   
   The console renders both with the local-time helper, so *创建时间* showed a time 
eight hours before the topic existed, while the audit row the same request 
wrote carried `22:26:45`. Every other writer in the service stamps its columns 
from the JVM clock, so the reservation was the only writer that could disagree 
with the row's own update time — and the disagreement equals the offset between 
the two hosts, whatever that offset is.
   
   ## Fix
   
   Reserve the row with both bookkeeping columns supplied from the studio clock 
the update path already uses, so one row can never mix clocks:
   
   ```java
   LocalDateTime stampedAt = LocalDateTime.now();
   jdbc.update("INSERT INTO rmq_instance_topic (name, instance_id, cluster_id, 
status, topic_type, gmt_create, gmt_modified)"
           + " VALUES (?, ?, ?, 'PENDING', ?, ?, ?)", ..., stampedAt, 
stampedAt);
   ```
   
   The zone is deliberately not re-chosen here: the PR only stops the row from 
depending on the database's clock, and keeps the clock the create path already 
applies to the same rows. (Whether the registry should move to UTC wholesale is 
the separate question the alert/notification surfaces are already deciding 
elsewhere.)
   
   ## Tests
   
   `ResourceOwnershipGuardTest` gains one case per table. Each recreates the 
shipped table with the same columns but without the `DEFAULT CURRENT_TIMESTAMP` 
clauses, so the test observes whether the reservation supplies the stamps 
instead of the database. Before the fix both fail with the reservation's own 
statement:
   
   ```
   INSERT INTO rmq_instance_topic (name, instance_id, cluster_id, status, 
topic_type) VALUES (?, ?, ?, 'PENDING', ?)
   → NULL not allowed for column "gmt_create"
   ```
   
   After the fix (JDK 21, H2, no MySQL needed):
   
   ```
   Tests run: 35, Failures: 0, Errors: 0, Skipped: 0   
(ResourceOwnershipGuardTest)
   Tests run: 278, Failures: 0, Errors: 0, Skipped: 0  
(ResourceOwnershipGuardTest, InstanceServiceTest, MetadataServiceTest, 
RocketMQAdminClientImplTest)
   ```
   
   Red and related-run logs are attached in the 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