重复两次
This commit is contained in:
parent
8a14ae619f
commit
cfe5bfdf6f
@ -13,15 +13,21 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/v1/integrations/wecom")
|
||||
public class WecomCallbackController {
|
||||
private static final Logger log = LoggerFactory.getLogger(WecomCallbackController.class);
|
||||
private static final long MESSAGE_DEDUP_TTL_SECONDS = 600;
|
||||
private final FoundationProperties properties;
|
||||
private final WecomClient wecomClient;
|
||||
private final WecomCryptoService wecomCryptoService;
|
||||
private final AgentOrchestratorService agentOrchestratorService;
|
||||
private final XmlMapper xmlMapper = new XmlMapper();
|
||||
private final Map<String, Long> processedMessages = new ConcurrentHashMap<>();
|
||||
|
||||
public WecomCallbackController(
|
||||
FoundationProperties properties,
|
||||
@ -79,6 +85,11 @@ public class WecomCallbackController {
|
||||
return "success";
|
||||
}
|
||||
|
||||
if (isDuplicateMessage(msg)) {
|
||||
log.info("wecom callback duplicate message ignored fromUser={} msgId={}", msg.getFromUserName(), msg.getMsgId());
|
||||
return "success";
|
||||
}
|
||||
|
||||
log.info("wecom callback invoking agent orchestrator agentId={} fromUser={}", properties.getWecom().getCrmAgentId(), msg.getFromUserName());
|
||||
String reply = agentOrchestratorService.handleMessage(properties.getWecom().getCrmAgentId(), msg.getFromUserName(), userText);
|
||||
reply = (reply == null || reply.isBlank())
|
||||
@ -113,6 +124,30 @@ public class WecomCallbackController {
|
||||
return xmlMapper.readValue(body, WecomIncomingMessage.class);
|
||||
}
|
||||
|
||||
private boolean isDuplicateMessage(WecomIncomingMessage msg) {
|
||||
evictExpiredMessages();
|
||||
String key = messageDedupKey(msg);
|
||||
Long previous = processedMessages.putIfAbsent(key, Instant.now().getEpochSecond());
|
||||
return previous != null;
|
||||
}
|
||||
|
||||
private String messageDedupKey(WecomIncomingMessage msg) {
|
||||
if (msg.getMsgId() != null && !msg.getMsgId().isBlank()) {
|
||||
return msg.getMsgId();
|
||||
}
|
||||
return "%s:%s:%s:%s".formatted(
|
||||
msg.getFromUserName(),
|
||||
msg.getToUserName(),
|
||||
msg.getCreateTime(),
|
||||
msg.getContent()
|
||||
);
|
||||
}
|
||||
|
||||
private void evictExpiredMessages() {
|
||||
long expireBefore = Instant.now().minusSeconds(MESSAGE_DEDUP_TTL_SECONDS).getEpochSecond();
|
||||
processedMessages.entrySet().removeIf(entry -> entry.getValue() < expireBefore);
|
||||
}
|
||||
|
||||
private String preview(String text) {
|
||||
if (text == null || text.isBlank()) {
|
||||
return "";
|
||||
|
||||
@ -15,6 +15,10 @@ public class WecomIncomingMessage {
|
||||
private String msgType;
|
||||
@JacksonXmlProperty(localName = "Content")
|
||||
private String content;
|
||||
@JacksonXmlProperty(localName = "CreateTime")
|
||||
private Long createTime;
|
||||
@JacksonXmlProperty(localName = "MsgId")
|
||||
private String msgId;
|
||||
|
||||
public String getToUserName() { return toUserName; }
|
||||
public void setToUserName(String toUserName) { this.toUserName = toUserName; }
|
||||
@ -24,4 +28,8 @@ public class WecomIncomingMessage {
|
||||
public void setMsgType(String msgType) { this.msgType = msgType; }
|
||||
public String getContent() { return content; }
|
||||
public void setContent(String content) { this.content = content; }
|
||||
public Long getCreateTime() { return createTime; }
|
||||
public void setCreateTime(Long createTime) { this.createTime = createTime; }
|
||||
public String getMsgId() { return msgId; }
|
||||
public void setMsgId(String msgId) { this.msgId = msgId; }
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user