From 35458a674ef59cd056db1192776237ca8717507e Mon Sep 17 00:00:00 2001 From: hy001 Date: Sat, 23 May 2026 12:27:44 +0800 Subject: [PATCH 1/2] fix: make country dashboard backfill atomic --- .../adapter/app/user/DatavRestController.java | 14 ++++++++++---- .../app/datav/CountryDashboardServiceImpl.java | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/DatavRestController.java b/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/DatavRestController.java index ac6c1f2c..728b0c11 100644 --- a/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/DatavRestController.java +++ b/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/user/DatavRestController.java @@ -146,15 +146,21 @@ public class DatavRestController extends BaseController { } LocalDate parsedStartDate = LocalDate.parse(startDate); LocalDate parsedEndDate = LocalDate.parse(endDate); - List refreshedTimezones = countryDashboardBackfillLockService.call( - () -> countryDashboardGameMetricService.refreshRange( - parsedStartDate, parsedEndDate, sysOrigin, statTimezones)); + Map refreshed = countryDashboardBackfillLockService.call(() -> { + List countryTimezones = countryDashboardDailyMetricService.refreshRange( + parsedStartDate, parsedEndDate, sysOrigin, statTimezones); + List gameTimezones = countryDashboardGameMetricService.refreshRange( + parsedStartDate, parsedEndDate, sysOrigin, statTimezones); + return Map.of( + "countryStatTimezones", countryTimezones, + "gameStatTimezones", gameTimezones); + }); return Map.of( "status", "success", "startDate", parsedStartDate.toString(), "endDate", parsedEndDate.toString(), "sysOrigin", sysOrigin, - "statTimezones", refreshedTimezones); + "statTimezones", refreshed); } private CountryDashboardCO emptyCountryDashboard(CountryDashboardQryCmd cmd) { diff --git a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardServiceImpl.java b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardServiceImpl.java index f0a227aa..fb134cf3 100644 --- a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardServiceImpl.java +++ b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/datav/CountryDashboardServiceImpl.java @@ -292,7 +292,7 @@ public class CountryDashboardServiceImpl implements CountryDashboardService { limit = Math.min(100, limit); QueryCondition condition = QueryCondition.of(cmd); - String countryCodes = trimToNull(cmd == null ? null : cmd.getCountryCodes()); + String countryCodes = QueryCondition.trimToNull(cmd == null ? null : cmd.getCountryCodes()); long total = safeLong(countryDashboardDAO.countRechargeDetails( condition.startTime, condition.endTime, condition.countryKeyword, countryCodes, condition.sysOrigin, condition.storageTimezoneOffset, condition.statTimezoneOffset)); From 0bf810261f0304e70d1cc20dc684372c6386aae0 Mon Sep 17 00:00:00 2001 From: hy001 Date: Sat, 23 May 2026 13:17:06 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=A6=96=E5=86=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ResidentCpActivityServiceImpl.java | 2 -- .../ResidentCpActivityServiceImplTest.java | 35 +++++++++++++++++++ .../app/command/user/SendCpApplyCmdExe.java | 11 ++++++ .../command/user/SendCpApplyCmdExeTest.java | 12 +++++-- .../props/ActivitySourceGroupGatewayImpl.java | 4 --- ...sActivityRewardGroupClientServiceImpl.java | 4 --- 6 files changed, 56 insertions(+), 12 deletions(-) diff --git a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImpl.java b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImpl.java index 72a957fe..e9abe9d6 100644 --- a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImpl.java +++ b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImpl.java @@ -120,8 +120,6 @@ public class ResidentCpActivityServiceImpl implements ResidentCpActivityService private void validateConfig(ResidentCpConfigSaveCmd cmd) { ResponseAssert.notBlank(ResponseErrorCode.REQUEST_PARAMETER_ERROR, cmd.getSysOrigin()); List levels = sortedLevels(cmd.getLevels()); - ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, - "CP levels must contain exactly 6 items.", levels.size() == CP_LEVEL_COUNT); Set levelSet = new HashSet<>(); long previousRequiredValue = -1L; for (ResidentCpLevelConfigSaveCmd level : levels) { diff --git a/rc-service/rc-service-console/console-application/src/test/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImplTest.java b/rc-service/rc-service-console/console-application/src/test/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImplTest.java index b47bb751..2ddd8433 100644 --- a/rc-service/rc-service-console/console-application/src/test/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImplTest.java +++ b/rc-service/rc-service-console/console-application/src/test/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImplTest.java @@ -1,12 +1,17 @@ package com.red.circle.console.app.service.app.activity; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.red.circle.console.app.dto.clienobject.app.activity.cp.ResidentCpConfigCO; import com.red.circle.console.app.dto.clienobject.app.activity.cp.ResidentCpLevelConfigCO; +import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpConfigSaveCmd; +import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpLevelConfigSaveCmd; import com.red.circle.console.app.service.app.sys.CpCabinConfigService; import com.red.circle.framework.dto.PageResult; import com.red.circle.other.inner.model.cmd.sys.SysCpCabinConfigQryCmd; @@ -41,6 +46,29 @@ class ResidentCpActivityServiceImplTest { assertEquals(0L, result.getLevels().get(5).getRequiredIntimacyValue()); } + @Test + void saveConfigShouldNotRequireExactLevelCount() { + CpCabinConfigService cpCabinConfigService = mock(CpCabinConfigService.class); + ResidentCpActivityServiceImpl service = new ResidentCpActivityServiceImpl( + cpCabinConfigService); + PageResult page = new PageResult<>(); + page.setRecords(List.of()); + when(cpCabinConfigService.getCpCabin(any(SysCpCabinConfigQryCmd.class))).thenReturn(page); + + ResidentCpConfigSaveCmd cmd = new ResidentCpConfigSaveCmd() + .setSysOrigin("likei") + .setLevels(List.of( + level(0, 0L), + level(1, 100L), + level(2, 200L), + level(3, 300L), + level(4, 400L) + )); + + assertDoesNotThrow(() -> service.saveConfig(cmd)); + verify(cpCabinConfigService, times(5)).addCpCabin(any(SysCpCabinConfigDTO.class)); + } + private static SysCpCabinConfigDTO config(Long id, Long sort, Long unlockValue) { return new SysCpCabinConfigDTO() .setId(id) @@ -48,4 +76,11 @@ class ResidentCpActivityServiceImplTest { .setCabinUnlockValue(unlockValue) .setSort(sort); } + + private static ResidentCpLevelConfigSaveCmd level(Integer level, Long requiredValue) { + return new ResidentCpLevelConfigSaveCmd() + .setLevel(level) + .setLevelName("CP " + level + "级") + .setRequiredIntimacyValue(requiredValue); + } } diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/SendCpApplyCmdExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/SendCpApplyCmdExe.java index ecb456df..c7a65acb 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/SendCpApplyCmdExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/SendCpApplyCmdExe.java @@ -71,6 +71,12 @@ public class SendCpApplyCmdExe { public boolean autoCreateFromCpGift(Long sendUserId, Long acceptUserId, String sysOrigin, String relationTypeValue) { + if (Objects.equals(sendUserId, acceptUserId)) { + log.info( + "[CP] skip auto create cp apply from self gift, sendUserId={}, relationType={}", + sendUserId, relationTypeValue); + return false; + } try { process(sendUserId, acceptUserId, sysOrigin, relationTypeValue, false); return true; @@ -156,6 +162,11 @@ public class SendCpApplyCmdExe { Map map = OfficialNoticeUtils.buildUserProfile(userProfile); map.put("applyType", isReconcile ? "RECONCILE" : "APPLY"); map.put("relationType", relationType.name()); + map.put("acceptUserId", acceptUserProfile.getId()); + map.put("acceptAccount", acceptUserProfile.getAccount()); + map.put("acceptActualAccount", acceptUserProfile.actualAccount()); + map.put("acceptNickname", acceptUserProfile.getUserNickname()); + map.put("acceptUserAvatar", acceptUserProfile.getUserAvatar()); officialNoticeClient.send(NoticeExtTemplateTypeCmd.builder() .toAccount(acceptUserId) .noticeType(OfficialNoticeTypeEnum.CP_BUILD) diff --git a/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/SendCpApplyCmdExeTest.java b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/SendCpApplyCmdExeTest.java index d2b1f809..a8d14460 100644 --- a/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/SendCpApplyCmdExeTest.java +++ b/rc-service/rc-service-other/other-application/src/test/java/com/red/circle/other/app/command/user/SendCpApplyCmdExeTest.java @@ -49,9 +49,19 @@ class SendCpApplyCmdExeTest { verify(fixture.cpApplyService, never()).save(any(CpApply.class)); } + @Test + void autoCreateFromCpGiftShouldSkipSelfGift() { + Fixture fixture = new Fixture(1, 1); + + assertFalse(fixture.exe.autoCreateFromCpGift(1001L, 1001L, "LIKEI", "BROTHER")); + verify(fixture.cpApplyService, never()).save(any(CpApply.class)); + verify(fixture.userRegionGateway, never()).checkEqRegion(any(), any()); + } + private static class Fixture { private final CpApplyService cpApplyService = mock(CpApplyService.class); + private final UserRegionGateway userRegionGateway = mock(UserRegionGateway.class); private final SendCpApplyCmdExe exe; private Fixture(Integer sendSex, Integer acceptSex) { @@ -62,8 +72,6 @@ class SendCpApplyCmdExeTest { EnumConfigCacheService enumConfigCacheService = mock(EnumConfigCacheService.class); UserProfileGateway userProfileGateway = mock(UserProfileGateway.class); UserProfileAppConvertor userProfileAppConvertor = mock(UserProfileAppConvertor.class); - UserRegionGateway userRegionGateway = mock(UserRegionGateway.class); - UserProfile sendProfile = new UserProfile(); UserProfile acceptProfile = new UserProfile(); UserProfileDTO sendProfileDTO = profile(1001L, sendSex); diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/props/ActivitySourceGroupGatewayImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/props/ActivitySourceGroupGatewayImpl.java index 7661e137..5437b727 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/props/ActivitySourceGroupGatewayImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/props/ActivitySourceGroupGatewayImpl.java @@ -5,7 +5,6 @@ import com.red.circle.common.business.enums.PropsActivityRewardEnum; import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.core.response.CommonErrorCode; import com.red.circle.other.domain.gateway.props.ActivitySourceGroupGateway; -import com.red.circle.other.infra.common.activity.VipActivityRewardCommon; import com.red.circle.other.infra.common.props.PropsResourcesCommon; import com.red.circle.other.infra.convertor.material.PropsActivityInfraConvertor; import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardConfig; @@ -383,8 +382,6 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa return rewardGroupConfigMap.values().stream() .flatMap(Collection::stream) .filter(config -> PropsActivityRewardEnum.PROPS.eq(config.getType())) - .filter(config -> Objects.equals(config.getDetailType(), - VipActivityRewardCommon.VIP_DETAIL_TYPE)) .map(config -> DataTypeUtils.toLong(config.getContent())) .filter(Objects::nonNull) .collect(Collectors.toSet()); @@ -408,7 +405,6 @@ public class ActivitySourceGroupGatewayImpl implements ActivitySourceGroupGatewa private boolean isVipLevelReward(PropsActivityRewardConfig rewardConfig, Set vipConfigIds) { return PropsActivityRewardEnum.PROPS.eq(rewardConfig.getType()) - && Objects.equals(rewardConfig.getDetailType(), VipActivityRewardCommon.VIP_DETAIL_TYPE) && vipConfigIds.contains(DataTypeUtils.toLong(rewardConfig.getContent())); } diff --git a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/props/impl/PropsActivityRewardGroupClientServiceImpl.java b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/props/impl/PropsActivityRewardGroupClientServiceImpl.java index 3bd230ef..e42396d5 100644 --- a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/props/impl/PropsActivityRewardGroupClientServiceImpl.java +++ b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/props/impl/PropsActivityRewardGroupClientServiceImpl.java @@ -4,7 +4,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.red.circle.common.business.enums.PropsActivityRewardEnum; import com.red.circle.framework.dto.PageResult; -import com.red.circle.other.infra.common.activity.VipActivityRewardCommon; import com.red.circle.other.app.inner.convertor.material.PropsInnerConvertor; import com.red.circle.other.app.inner.service.material.props.PropsActivityRewardGroupClientService; import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardConfig; @@ -354,8 +353,6 @@ public class PropsActivityRewardGroupClientServiceImpl implements private Set getVipLevelConfigIds(List configs) { return configs.stream() .filter(config -> Objects.equals(config.getType(), PropsActivityRewardEnum.PROPS.name())) - .filter(config -> Objects.equals(config.getDetailType(), - VipActivityRewardCommon.VIP_DETAIL_TYPE)) .map(config -> DataTypeUtils.toLong(config.getContent())) .filter(Objects::nonNull) .collect(Collectors.toSet()); @@ -375,7 +372,6 @@ public class PropsActivityRewardGroupClientServiceImpl implements private boolean isVipLevelReward(PropsActivityRewardConfig config, Map vipConfigMap) { return Objects.equals(config.getType(), PropsActivityRewardEnum.PROPS.name()) - && Objects.equals(config.getDetailType(), VipActivityRewardCommon.VIP_DETAIL_TYPE) && vipConfigMap.containsKey(DataTypeUtils.toLong(config.getContent())); }