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]