feat: add receive message reconciliation helper

This commit is contained in:
zhaoyilun
2026-07-11 00:38:06 +08:00
parent 57db83d36c
commit d94d0a318a
6 changed files with 252 additions and 8 deletions

View File

@@ -0,0 +1,104 @@
package isphere
import "math"
const reconciliationMediumTimestampWindowMillis int64 = 3000
type MessageReconciliationCandidate struct {
Source string
MessageID string
ConversationID string
SenderID string
TimestampUnixMilli int64
BodyPresent bool
AttachmentPresent bool
}
type MessageReconciliationSummary struct {
LeftCount int
RightCount int
StrongMatches int
MediumMatches int
UnmatchedLeft int
UnmatchedRight int
AutoMergeRecommended bool
}
func ReconcileMessageSources(left, right []MessageReconciliationCandidate) MessageReconciliationSummary {
matchedLeft := make([]bool, len(left))
matchedRight := make([]bool, len(right))
summary := MessageReconciliationSummary{LeftCount: len(left), RightCount: len(right)}
for leftIndex, leftCandidate := range left {
if leftCandidate.MessageID == "" {
continue
}
for rightIndex, rightCandidate := range right {
if matchedRight[rightIndex] || rightCandidate.MessageID == "" {
continue
}
if leftCandidate.MessageID == rightCandidate.MessageID {
matchedLeft[leftIndex] = true
matchedRight[rightIndex] = true
summary.StrongMatches++
break
}
}
}
for leftIndex, leftCandidate := range left {
if matchedLeft[leftIndex] {
continue
}
for rightIndex, rightCandidate := range right {
if matchedRight[rightIndex] {
continue
}
if isMediumMessageMatch(leftCandidate, rightCandidate) {
matchedLeft[leftIndex] = true
matchedRight[rightIndex] = true
summary.MediumMatches++
break
}
}
}
summary.UnmatchedLeft = countFalse(matchedLeft)
summary.UnmatchedRight = countFalse(matchedRight)
summary.AutoMergeRecommended = shouldRecommendAutoMerge(summary)
return summary
}
func isMediumMessageMatch(left, right MessageReconciliationCandidate) bool {
if left.ConversationID == "" || right.ConversationID == "" || left.ConversationID != right.ConversationID {
return false
}
if left.SenderID == "" || right.SenderID == "" || left.SenderID != right.SenderID {
return false
}
if left.TimestampUnixMilli <= 0 || right.TimestampUnixMilli <= 0 {
return false
}
delta := int64(math.Abs(float64(left.TimestampUnixMilli - right.TimestampUnixMilli)))
return delta <= reconciliationMediumTimestampWindowMillis
}
func countFalse(values []bool) int {
count := 0
for _, value := range values {
if !value {
count++
}
}
return count
}
func shouldRecommendAutoMerge(summary MessageReconciliationSummary) bool {
if summary.LeftCount == 0 || summary.RightCount == 0 {
return false
}
if summary.UnmatchedLeft != 0 || summary.UnmatchedRight != 0 || summary.MediumMatches != 0 {
return false
}
return summary.StrongMatches == summary.LeftCount && summary.StrongMatches == summary.RightCount
}