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

Reply via email to