From 65732197513c3d53fe50054285fa7d04a15d83a1 Mon Sep 17 00:00:00 2001 From: hy001 Date: Mon, 25 May 2026 17:07:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=80=81=E7=A4=BC=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/command/user/ProcessCpApplyCmd.java | 14 +++++++++-- .../user/query/CpApplyStatusQryExe.java | 1 - .../command/user/ProcessCpApplyCmdTest.java | 18 ++++++++++++++ .../user/query/CpApplyStatusQryExeTest.java | 5 ++-- .../user/user/impl/CpApplyServiceImpl.java | 24 +++++++------------ 5 files changed, 42 insertions(+), 20 deletions(-) diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/ProcessCpApplyCmd.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/ProcessCpApplyCmd.java index fd0fc6b3..6d255bfd 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/ProcessCpApplyCmd.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/ProcessCpApplyCmd.java @@ -19,6 +19,7 @@ import com.red.circle.other.infra.enums.user.user.CpApplyStatus; import com.red.circle.other.infra.enums.user.user.CpRelationshipType; import com.red.circle.other.inner.asserts.user.UserRelationErrorCode; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; @@ -40,6 +41,7 @@ public class ProcessCpApplyCmd { private static final int CP_MAX_COUNT = 1; private static final int FRIEND_MAX_COUNT = 3; + private static final long APPLY_WAIT_EXPIRE_HOURS = 24L; private final CpApplyService cpApplyService; private final CpValueService cpValueService; @@ -60,8 +62,9 @@ public class ProcessCpApplyCmd { String relationType = CpRelationshipType.normalize(cpApply.getRelationType()); // 状态错误 - ResponseAssert.isTrue(CommonErrorCode.STATE_ERROR, - Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name())); + ResponseAssert.isTrue(CommonErrorCode.STATE_ERROR, + Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name())); + ResponseAssert.isFalse(CommonErrorCode.STATE_ERROR, isOverdueWait(cpApply)); boolean agree = isAgree(cmd); boolean isReconcile = false; @@ -114,6 +117,13 @@ public class ProcessCpApplyCmd { sendProcessNotice(cpApply, true); } + private boolean isOverdueWait(CpApply cpApply) { + return Objects.equals(cpApply.getStatus(), CpApplyStatus.WAIT.name()) + && Objects.nonNull(cpApply.getCreateTime()) + && cpApply.getCreateTime().toLocalDateTime() + .isBefore(LocalDateTime.now().minusHours(APPLY_WAIT_EXPIRE_HOURS)); + } + private void sendProcessNotice(CpApply cpApply, boolean agree) { try { UserProfile senderProfile = userProfileGateway.getByUserId(cpApply.getSendApplyUserId()); diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/CpApplyStatusQryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/CpApplyStatusQryExe.java index 3eea2de8..04cc9489 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/CpApplyStatusQryExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/CpApplyStatusQryExe.java @@ -26,7 +26,6 @@ public class CpApplyStatusQryExe { return null; } if (isOverdueWait(cpApply)) { - cpApplyService.expireWaitById(cpApply.getId()); return CpApplyStatus.EXPIRE.name(); } return cpApply.getStatus(); diff --git a/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/ProcessCpApplyCmdTest.java b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/ProcessCpApplyCmdTest.java index f732b9af..028b0100 100644 --- a/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/ProcessCpApplyCmdTest.java +++ b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/ProcessCpApplyCmdTest.java @@ -22,6 +22,8 @@ import com.red.circle.other.infra.database.rds.service.user.user.CpApplyService; import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService; import com.red.circle.other.infra.database.rds.service.user.user.CpValueService; import com.red.circle.other.infra.enums.user.user.CpApplyStatus; +import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; import org.junit.jupiter.api.Assertions; @@ -84,6 +86,22 @@ class ProcessCpApplyCmdTest { verify(fixture.imMessageClient, never()).sendCustomMessage(any(CustomC2cMsgBodyCmd.class)); } + @Test + void processOverdueWaitApplyShouldFailStateError() { + Fixture fixture = new Fixture("CP"); + CpApply overdueApply = apply("CP"); + overdueApply.setCreateTime(Timestamp.valueOf(LocalDateTime.now().minusHours(25))); + when(fixture.cpApplyService.getById(3001L)).thenReturn(overdueApply); + + Assertions.assertThrows(RuntimeException.class, () -> fixture.exe.execute(processCmd(true))); + + verify(fixture.cpApplyService, never()).changeStatusById(eq(3001L), + any(CpApplyStatus.class)); + verify(fixture.cpRelationshipService, never()).addCp(any(Long.class), any(Long.class), + nullable(Long.class), any(String.class), any(String.class)); + verify(fixture.imMessageClient, never()).sendCustomMessage(any(CustomC2cMsgBodyCmd.class)); + } + @Test void agreeApplyShouldAutoRefuseOtherWaitAppliesBetweenSameUsersWithoutRejectedIm() { Fixture fixture = new Fixture("CP"); diff --git a/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/query/CpApplyStatusQryExeTest.java b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/query/CpApplyStatusQryExeTest.java index 11ea8ada..b798d7ad 100644 --- a/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/query/CpApplyStatusQryExeTest.java +++ b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/query/CpApplyStatusQryExeTest.java @@ -3,6 +3,7 @@ package com.red.circle.other.app.command.user.query; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,7 +35,7 @@ class CpApplyStatusQryExeTest { } @Test - void shouldExpireOverdueWaitApplyWhenQueryingStatus() { + void shouldReturnExpireForOverdueWaitApplyWithoutPersistingStatus() { CpApplyService cpApplyService = mock(CpApplyService.class); CpApply cpApply = new CpApply() .setId(3001L) @@ -45,7 +46,7 @@ class CpApplyStatusQryExeTest { CpApplyStatusQryExe exe = new CpApplyStatusQryExe(cpApplyService); assertEquals("EXPIRE", exe.execute(cmd(3001L))); - verify(cpApplyService).expireWaitById(3001L); + verify(cpApplyService, never()).expireWaitById(3001L); } private static CpApplyStatusQueryCmd cmd(Long applyId) { diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/impl/CpApplyServiceImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/impl/CpApplyServiceImpl.java index 9a9aadae..9f886577 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/impl/CpApplyServiceImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/impl/CpApplyServiceImpl.java @@ -111,27 +111,21 @@ public class CpApplyServiceImpl extends BaseServiceImpl imp @Override public boolean expireWaitById(Long id) { - return update() - .set(CpApply::getStatus, CpApplyStatus.EXPIRE.name()) - .set(CpApply::getUpdateTime, LocalDateTime.now()) + return Optional.ofNullable(query() + .select(CpApply::getId) .eq(CpApply::getId, id) .eq(CpApply::getStatus, CpApplyStatus.WAIT.name()) - .execute(); + .lt(CpApply::getCreateTime, waitExpireBefore()) + .last(PageConstant.LIMIT_ONE) + .getOne()) + .map(cpApply -> Objects.nonNull(cpApply.getId())) + .orElse(Boolean.FALSE); } @Override public void expireOverdueWaitApplies(Long userId) { - if (Objects.isNull(userId)) { - return; - } - update() - .set(CpApply::getStatus, CpApplyStatus.EXPIRE.name()) - .set(CpApply::getUpdateTime, LocalDateTime.now()) - .eq(CpApply::getStatus, CpApplyStatus.WAIT.name()) - .lt(CpApply::getCreateTime, waitExpireBefore()) - .and(where -> where.eq(CpApply::getSendApplyUserId, userId) - .or().eq(CpApply::getAcceptApplyUserId, userId)) - .execute(); + // The production status column does not accept a persisted EXPIRE value. + // Expiration is derived from create_time so old WAIT rows do not block new applies. } private Timestamp waitExpireBefore() {