记录重复投递 payload 差异

This commit is contained in:
andy
2026-07-09 18:40:56 +08:00
parent 1282d4aede
commit c1f9870fce
8 changed files with 314 additions and 10 deletions

View File

@@ -3,6 +3,7 @@ package cn.nianxx.thhotel.platform.message.service;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -32,6 +33,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest(classes = ThHotelApplication.class)
@@ -50,6 +52,9 @@ class SourceMessageCaptureServiceImplTest {
@Autowired
private SourceMessagePayloadMapper payloadMapper;
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
void shouldCaptureReceivedEmailAndExposeOnlySafeSummaryForQueries() {
CaptureSourceMessageCommand command = new CaptureSourceMessageCommand(
@@ -164,6 +169,19 @@ class SourceMessageCaptureServiceImplTest {
assertThat(payload.getPayloadJson()).contains("\"version\":1");
assertThat(payload.getPayloadJson()).doesNotContain("\"version\":2");
Long duplicatePayloadCount = jdbcTemplate.queryForObject("""
SELECT COUNT(*)
FROM platform_source_message_payload_duplicate
WHERE inbox_id = ?
AND original_payload_sha256 = ?
AND duplicate_payload_sha256 <> ?
AND payload_json LIKE '%"version":2%'
AND provider_frame_id = 'frame-duplicate-002'
AND provider_session_id = 'session-duplicate'
AND schema_version = 'agentbus-outlook-v1'
""", Long.class, firstResult.inboxId(), payload.getPayloadSha256(), payload.getPayloadSha256());
assertThat(duplicatePayloadCount).isEqualTo(1L);
SourceMessageInboxEntity inbox = inboxMapper.selectById(firstResult.inboxId());
assertThat(inbox.getDuplicatePayloadChanged()).isTrue();
assertThat(inbox.getSafeErrorSummary()).contains("重复投递 payload");
@@ -335,4 +353,57 @@ class SourceMessageCaptureServiceImplTest {
assertThat(result.duplicatePayloadChanged()).isTrue();
verify(localRepository).markDuplicatePayloadChanged(eq(99001L), any(String.class), any(LocalDateTime.class));
}
@Test
void shouldKeepIdempotentResultWhenDuplicatePayloadDiagnosticWriteFails() {
SourceMessageInboxRepository localRepository = mock(SourceMessageInboxRepository.class);
SourceMessageCaptureService localService = new SourceMessageCaptureServiceImpl(
localRepository,
new SourceMessageSafetySanitizer()
);
SourceMessageInboxSnapshot existing = new SourceMessageInboxSnapshot(
99002L,
"HOTEL-TEST",
"AGENTBUS",
"EMAIL",
"mail-diagnostic-fail-001",
"conversation-diagnostic-fail",
"different-payload-hash",
"RECEIVED",
true,
LocalDateTime.parse("2026-07-06T10:00:00"),
LocalDateTime.parse("2026-07-06T10:00:00"),
"g***@example.test",
"Duplicate diagnostic fail",
"Original body"
);
when(localRepository.findByIdempotencyKey("HOTEL-TEST", "AGENTBUS", "EMAIL", "mail-diagnostic-fail-001"))
.thenReturn(Optional.of(existing));
doThrow(new DuplicateKeyException("duplicate diagnostic payload"))
.when(localRepository).insertDuplicatePayload(any());
CaptureSourceMessageCommand command = new CaptureSourceMessageCommand(
"HOTEL-TEST",
"AGENTBUS",
"EMAIL",
"mail-diagnostic-fail-001",
"conversation-diagnostic-fail",
"frame-diagnostic-fail-001",
"session-diagnostic-fail",
Instant.parse("2026-07-06T10:00:00Z"),
"guest@example.test",
"Duplicate diagnostic fail",
"Changed body",
"<html>Changed body</html>",
"{\"source\":{\"external_message_id\":\"mail-diagnostic-fail-001\"},\"version\":2}",
"agentbus-outlook-v1",
List.of()
);
SourceMessageCaptureResult result = localService.capture(command);
assertThat(result.created()).isFalse();
assertThat(result.inboxId()).isEqualTo(99002L);
assertThat(result.duplicatePayloadChanged()).isTrue();
assertThat(result.captureStatus()).isEqualTo("RECEIVED");
}
}