This is an automated email from the ASF dual-hosted git repository.
lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git
The following commit(s) were added to refs/heads/rocketmq-studio by this push:
new 206c9a23 fix(dlq): preserve user properties and classify resend
outcome (#1416, #1436)
206c9a23 is described below
commit 206c9a2338dcf73bce26ccc6d34e3c1317b384da
Author: Yu Xinqiang <[email protected]>
AuthorDate: Tue Aug 11 00:26:05 2026 +0800
fix(dlq): preserve user properties and classify resend outcome (#1416,
#1436)
* [ISSUE #1415] Preserve user properties in DLQ resend
The resendOne method was only copying body, tags, and keys from the
original dead-letter message, dropping all user properties (trace IDs,
correlation IDs, custom headers). This fix copies all non-system
user properties from the original message before adding the Studio
provenance properties.
Fixes #1415
* [ISSUE #1435] Classify DLQ resend outcome accurately
The outcome was classified as SUCCESS for zero matches and PARTIAL
for total failure. This fix adds classifyOutcome() that distinguishes
NO_MESSAGES, FAILED, PARTIAL, and SUCCESS.
Fixes #1435
---
.../provider/apache/RocketMQDLQProvider.java | 28 ++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQDLQProvider.java
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQDLQProvider.java
index 5e31eed1..c0872f75 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQDLQProvider.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQDLQProvider.java
@@ -167,13 +167,13 @@ public class RocketMQDLQProvider implements DLQProvider {
String detail = String.format("instanceId=%s, group=%s, dlqTopic=%s,
targetTopic=%s, matched=%d, resent=%d, failed=%d",
instanceId, groupName, dlqTopic,
StringUtils.hasText(targetTopic) ? targetTopic : "<original>",
deadLetters.size(), resent, failed);
- recordAudit(groupName, detail, failed == 0 ? "SUCCESS" : "PARTIAL");
+ recordAudit(groupName, detail, classifyOutcome(deadLetters.size(),
resent, failed));
log.info("DLQ resend completed: {}", detail);
return DLQResendResultVO.builder()
.matched(deadLetters.size())
.resent(resent)
.failed(failed)
- .outcome(failed == 0 ? "SUCCESS" : "PARTIAL")
+ .outcome(classifyOutcome(deadLetters.size(), resent, failed))
.build();
}
@@ -268,6 +268,17 @@ public class RocketMQDLQProvider implements DLQProvider {
if (StringUtils.hasText(deadLetter.getKeys())) {
message.setKeys(deadLetter.getKeys());
}
+ // Copy user properties from the original message, skipping
system-reserved
+ // keys to avoid conflicts with broker-internal properties.
+ Map<String, String> userProperties =
deadLetter.getUserProperties();
+ if (userProperties != null) {
+ for (Map.Entry<String, String> entry :
userProperties.entrySet()) {
+ String key = entry.getKey();
+ if (!MessageConst.STRING_HASH_SET.contains(key)) {
+ message.putUserProperty(key, entry.getValue());
+ }
+ }
+ }
message.putUserProperty(ORIGIN_MESSAGE_ID_PROPERTY,
deadLetter.getMsgId());
message.putUserProperty(ORIGIN_TOPIC_PROPERTY,
deadLetter.getTopic());
SendResult sendResult = producer.send(message);
@@ -324,6 +335,19 @@ public class RocketMQDLQProvider implements DLQProvider {
return ShortLivedClientName.next("studio-dlq-resend");
}
+ private String classifyOutcome(int matched, int resent, int failed) {
+ if (matched == 0) {
+ return "NO_MESSAGES";
+ }
+ if (resent == 0 && failed > 0) {
+ return "FAILED";
+ }
+ if (failed > 0) {
+ return "PARTIAL";
+ }
+ return "SUCCESS";
+ }
+
private void recordAudit(String groupName, String detail, String result) {
try {
auditService.record("RESEND_DLQ", groupName, detail, result);