fix(wecom): correctly retain boundary message during dedupe map rotation
When the dedupe map rotates, the previous logic entirely cleared the map, meaning the message that triggered the rotation was immediately forgotten and could be duplicated immediately. This change seeds the new map with the current message to prevent that. Also adds a defensive nil check.
This commit is contained in:
parent
1e2ab4a5e5
commit
8640c8177c
2 changed files with 16 additions and 7 deletions
|
|
@ -14,14 +14,18 @@ func markMessageProcessed(msgMu *sync.RWMutex, processedMsgs *map[string]bool, m
|
||||||
msgMu.Lock()
|
msgMu.Lock()
|
||||||
defer msgMu.Unlock()
|
defer msgMu.Unlock()
|
||||||
|
|
||||||
|
if *processedMsgs == nil {
|
||||||
|
*processedMsgs = make(map[string]bool)
|
||||||
|
}
|
||||||
|
|
||||||
if (*processedMsgs)[msgID] {
|
if (*processedMsgs)[msgID] {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
(*processedMsgs)[msgID] = true
|
(*processedMsgs)[msgID] = true
|
||||||
|
|
||||||
// Keep existing behavior: when over limit, reset dedupe map entirely.
|
// When over limit, reset dedupe map but keep the current message.
|
||||||
if len(*processedMsgs) > maxEntries {
|
if len(*processedMsgs) > maxEntries {
|
||||||
*processedMsgs = make(map[string]bool)
|
*processedMsgs = map[string]bool{msgID: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
||||||
|
|
@ -60,14 +60,19 @@ func TestMarkMessageProcessed_RotationClearsMapAtBoundary(t *testing.T) {
|
||||||
t.Fatalf("expected map size 1 after first insert, got %d", len(processed))
|
t.Fatalf("expected map size 1 after first insert, got %d", len(processed))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inserting second unique message exceeds maxEntries and should reset map.
|
// Inserting second unique message exceeds maxEntries and should reset map, but keep the new message.
|
||||||
if ok := markMessageProcessed(&mu, &processed, "msg-2", 1); !ok {
|
if ok := markMessageProcessed(&mu, &processed, "msg-2", 1); !ok {
|
||||||
t.Fatalf("second unique message should be accepted")
|
t.Fatalf("second unique message should be accepted")
|
||||||
}
|
}
|
||||||
if len(processed) != 0 {
|
if len(processed) != 1 {
|
||||||
t.Fatalf("expected map to be reset after rotation, got size %d", len(processed))
|
t.Fatalf("expected map to retain current message after rotation, got size %d", len(processed))
|
||||||
}
|
}
|
||||||
if processed["msg-2"] {
|
if !processed["msg-2"] {
|
||||||
t.Fatalf("expected current message marker to be cleared after rotation")
|
t.Fatalf("expected current message marker to be retained after rotation")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because msg-2 was retained, an immediate duplicate should be rejected.
|
||||||
|
if ok := markMessageProcessed(&mu, &processed, "msg-2", 1); ok {
|
||||||
|
t.Fatalf("duplicate message immediately after rotation should be rejected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue