重复两次
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.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/v1/integrations/wecom")
|
@RequestMapping("/v1/integrations/wecom")
|
||||||
public class WecomCallbackController {
|
public class WecomCallbackController {
|
||||||
private static final Logger log = LoggerFactory.getLogger(WecomCallbackController.class);
|
private static final Logger log = LoggerFactory.getLogger(WecomCallbackController.class);
|
||||||
|
private static final long MESSAGE_DEDUP_TTL_SECONDS = 600;
|
||||||
private final FoundationProperties properties;
|
private final FoundationProperties properties;
|
||||||
private final WecomClient wecomClient;
|
private final WecomClient wecomClient;
|
||||||
private final WecomCryptoService wecomCryptoService;
|
private final WecomCryptoService wecomCryptoService;
|
||||||
private final AgentOrchestratorService agentOrchestratorService;
|
private final AgentOrchestratorService agentOrchestratorService;
|
||||||
private final XmlMapper xmlMapper = new XmlMapper();
|
private final XmlMapper xmlMapper = new XmlMapper();
|
||||||
|
private final Map<String, Long> processedMessages = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public WecomCallbackController(
|
public WecomCallbackController(
|
||||||
FoundationProperties properties,
|
FoundationProperties properties,
|
||||||
@ -79,6 +85,11 @@ public class WecomCallbackController {
|
|||||||
return "success";
|
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());
|
log.info("wecom callback invoking agent orchestrator agentId={} fromUser={}", properties.getWecom().getCrmAgentId(), msg.getFromUserName());
|
||||||
String reply = agentOrchestratorService.handleMessage(properties.getWecom().getCrmAgentId(), msg.getFromUserName(), userText);
|
String reply = agentOrchestratorService.handleMessage(properties.getWecom().getCrmAgentId(), msg.getFromUserName(), userText);
|
||||||
reply = (reply == null || reply.isBlank())
|
reply = (reply == null || reply.isBlank())
|
||||||
@ -113,6 +124,30 @@ public class WecomCallbackController {
|
|||||||
return xmlMapper.readValue(body, WecomIncomingMessage.class);
|
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) {
|
private String preview(String text) {
|
||||||
if (text == null || text.isBlank()) {
|
if (text == null || text.isBlank()) {
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@ -15,6 +15,10 @@ public class WecomIncomingMessage {
|
|||||||
private String msgType;
|
private String msgType;
|
||||||
@JacksonXmlProperty(localName = "Content")
|
@JacksonXmlProperty(localName = "Content")
|
||||||
private String content;
|
private String content;
|
||||||
|
@JacksonXmlProperty(localName = "CreateTime")
|
||||||
|
private Long createTime;
|
||||||
|
@JacksonXmlProperty(localName = "MsgId")
|
||||||
|
private String msgId;
|
||||||
|
|
||||||
public String getToUserName() { return toUserName; }
|
public String getToUserName() { return toUserName; }
|
||||||
public void setToUserName(String toUserName) { this.toUserName = 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 void setMsgType(String msgType) { this.msgType = msgType; }
|
||||||
public String getContent() { return content; }
|
public String getContent() { return content; }
|
||||||
public void setContent(String content) { this.content = 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