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

   ### Which Issue(s) This PR Fixes
   
   - Fixes #5049
   
   ### Brief Description
   
   `AliyunClientFactory.client` 
(server/src/main/java/org/apache/rocketmq/studio/provider/alibaba/AliyunClientFactory.java:62-65)
 published a new client with a bare `clients.computeIfAbsent(key, ignored -> 
createClient(...))`, while `invalidateCredential` (same file, line 70) evicted 
the matching entries with `clients.entrySet().removeIf(...)`. The two 
operations were not mutually exclusive: a lookup that had already started 
building its client while `CloudCredentialService.update` rotated the secret 
removed nothing (the entry did not exist yet), so the client built from the 
*old* secret was published into the cache right after the invalidation 
returned. The next lookup for that credential/region returned that stale client 
— the rotation reported success but subsequent Aliyun calls kept signing with 
the previous access key until another rotation or a restart.
   
   The fix makes creation and invalidation share the factory's monitor, exactly 
like the sibling `TencentClientFactory` already does: `client()` takes a lock 
for the `computeIfAbsent` publish (with a lock-free fast path for the hits) and 
`invalidateCredential` is `synchronized`, so a client that is still being 
created is always published *before* the eviction runs and is therefore evicted 
by it. A lookup that starts after invalidation completes builds a client from 
the updated credential.
   
   ### How Did You Test This Change?
   
   New deterministic regression 
`AliyunClientFactoryTest#invalidateCredentialShouldEvictClientCreatedDuringRotationTest`:
 a subclassed factory publishes a first client only after a latch is released, 
`createClient` signals when it is in flight, and a second thread calls the real 
`invalidateCredential` while that creation is still running; the test then 
asserts that the next `client(CREDENTIAL_ID, REGION)` is the replacement 
client, that the first client was closed and that exactly two clients were 
created.
   
   Red run on the unmodified tree:
   
   ```
   $ cd server && mvn -B -ntp test -Dtest=AliyunClientFactoryTest
   [ERROR] Tests run: 11, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 
4.393 s <<< FAILURE! -- in 
org.apache.rocketmq.studio.provider.alibaba.AliyunClientFactoryTest
   [ERROR] 
org.apache.rocketmq.studio.provider.alibaba.AliyunClientFactoryTest.invalidateCredentialShouldEvictClientCreatedDuringRotationTest
 -- Time elapsed: 0.032 s <<< FAILURE!
   [ERROR]   
AliyunClientFactoryTest.invalidateCredentialShouldEvictClientCreatedDuringRotationTest:162
   java.lang.AssertionError:
   Expecting actual:
     Mock for AsyncClient, hashCode: 59930654
   and:
     Mock for AsyncClient, hashCode: 1070319462
   to refer to the same object
   [ERROR] Tests run: 11, Failures: 1, Errors: 0, Skipped: 0
   [INFO] BUILD FAILURE
   ```
   
   Green run after the fix (same command, same test class):
   
   ```
   $ cd server && mvn -B -ntp test -Dtest=AliyunClientFactoryTest
   [INFO] You have 0 Checkstyle violations.
   [INFO] Tests run: 11, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 
4.497 s -- in 
org.apache.rocketmq.studio.provider.alibaba.AliyunClientFactoryTest
   [INFO] Tests run: 11, Failures: 0, Errors: 0, Skipped: 0
   [INFO] BUILD SUCCESS
   ```
   
   ### Checklist
   
   - [x] One coherent change; unrelated modifications are not bundled in
   - [x] Commit subject follows Conventional Commits
   - [x] Tests added or updated for non-trivial changes
   - [x] New UI text has both Chinese and English entries under `web/src/i18n/` 
— not applicable, no UI text changed
   - [x] Architecture constraints stay green (`mvn test` runs the ArchUnit 
checks) — only the locking discipline inside one existing class changed; no new 
type, package or dependency, and the ArchUnit rules run in the same reactor
   - [x] New source files carry the ASF license header — no new source file, 
the change is inside an existing file
   - [x] Documentation touched where behaviour changed (README / `docs/` / 
in-app help) — not applicable: cache internals only, the endpoint contracts and 
API shapes are unchanged
   


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