From c31e394558f06e1aa3424bc76b4c9e418d044f18 Mon Sep 17 00:00:00 2001 From: tanglong <842690096@qq.com> Date: Thu, 24 Sep 2026 14:33:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=AE=A1=E5=AE=B6=E5=A9=86?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=8A=B6=E6=80=81=E6=89=B9=E9=87=8F=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ngp/monthly/NgpMonthlyWeeklyService.java | 3 +- .../NgpPerformanceCacheRepository.java | 20 +++++++++++++ .../NgpPerformanceTotalService.java | 4 ++- .../monthly/NgpMonthlyWeeklyServiceTest.java | 28 +++++++++++++------ .../NgpPerformanceCacheRepositoryTest.java | 19 +++++++++++++ .../NgpPerformanceTotalServiceTest.java | 21 ++++++++++---- 6 files changed, 79 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/company/agentfoundation/ngp/monthly/NgpMonthlyWeeklyService.java b/src/main/java/com/company/agentfoundation/ngp/monthly/NgpMonthlyWeeklyService.java index 72f695f..0cd5823 100644 --- a/src/main/java/com/company/agentfoundation/ngp/monthly/NgpMonthlyWeeklyService.java +++ b/src/main/java/com/company/agentfoundation/ngp/monthly/NgpMonthlyWeeklyService.java @@ -79,9 +79,10 @@ public class NgpMonthlyWeeklyService { LocalDate monthEnd = month.atEndOfMonth(); LocalDate dataEnd = month.equals(currentMonth) ? today : monthEnd; LocalDateTime now = LocalDateTime.now(clock); + Map storedRefreshTimes = repository.findRefreshTimes(monthStart, dataEnd); Map cachedDates = new LinkedHashMap<>(); monthStart.datesUntil(dataEnd.plusDays(1)).forEach(date -> - cachedDates.put(date, repository.findRefreshTime(date).orElse(null))); + cachedDates.put(date, storedRefreshTimes.get(date))); List missingDates = cachedDates.entrySet().stream() .filter(entry -> entry.getValue() == null) .map(Map.Entry::getKey) diff --git a/src/main/java/com/company/agentfoundation/ngp/performance/NgpPerformanceCacheRepository.java b/src/main/java/com/company/agentfoundation/ngp/performance/NgpPerformanceCacheRepository.java index afb532d..bc17b87 100644 --- a/src/main/java/com/company/agentfoundation/ngp/performance/NgpPerformanceCacheRepository.java +++ b/src/main/java/com/company/agentfoundation/ngp/performance/NgpPerformanceCacheRepository.java @@ -62,6 +62,26 @@ public class NgpPerformanceCacheRepository { return rows.stream().findFirst(); } + public Map findRefreshTimes(LocalDate startDate, LocalDate endDate) { + Map result = new LinkedHashMap<>(); + jdbcTemplate.query(""" + SELECT business_date, refreshed_at + FROM ngp_performance_daily_status + WHERE business_date BETWEEN ? AND ? + AND filter_signature = ? + ORDER BY business_date + """, + (RowCallbackHandler) resultSet -> result.put( + resultSet.getObject("business_date", LocalDate.class), + resultSet.getTimestamp("refreshed_at").toLocalDateTime() + ), + startDate, + endDate, + FILTER_SIGNATURE + ); + return Map.copyOf(result); + } + public Map aggregate(LocalDate startDate, LocalDate endDate) { Map result = new LinkedHashMap<>(); jdbcTemplate.query(""" diff --git a/src/main/java/com/company/agentfoundation/ngp/performance/NgpPerformanceTotalService.java b/src/main/java/com/company/agentfoundation/ngp/performance/NgpPerformanceTotalService.java index 292aada..08213d7 100644 --- a/src/main/java/com/company/agentfoundation/ngp/performance/NgpPerformanceTotalService.java +++ b/src/main/java/com/company/agentfoundation/ngp/performance/NgpPerformanceTotalService.java @@ -46,9 +46,11 @@ public class NgpPerformanceTotalService { public NgpPerformanceResult total(NgpPerformanceTotalRequest request) { validate(request); LocalDateTime now = LocalDateTime.now(BUSINESS_ZONE); + Map storedRefreshTimes = repository.findRefreshTimes( + request.startDate(), request.endDate()); Map cachedDates = new LinkedHashMap<>(); request.startDate().datesUntil(request.endDate().plusDays(1)).forEach(date -> - cachedDates.put(date, repository.findRefreshTime(date).orElse(null))); + cachedDates.put(date, storedRefreshTimes.get(date))); List missingDates = cachedDates.entrySet().stream() .filter(entry -> entry.getValue() == null) .map(Map.Entry::getKey) diff --git a/src/test/java/com/company/agentfoundation/ngp/monthly/NgpMonthlyWeeklyServiceTest.java b/src/test/java/com/company/agentfoundation/ngp/monthly/NgpMonthlyWeeklyServiceTest.java index 7bd4c4d..1b375cf 100644 --- a/src/test/java/com/company/agentfoundation/ngp/monthly/NgpMonthlyWeeklyServiceTest.java +++ b/src/test/java/com/company/agentfoundation/ngp/monthly/NgpMonthlyWeeklyServiceTest.java @@ -16,13 +16,13 @@ import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; +import java.util.LinkedHashMap; import java.util.List; -import java.util.Optional; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; 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; @@ -45,7 +45,7 @@ class NgpMonthlyWeeklyServiceTest { @Test void currentMonthOnlyRequiresDatesThroughToday() { - when(repository.findRefreshTime(any())).thenReturn(Optional.empty()); + when(repository.findRefreshTimes(any(), any())).thenReturn(Map.of()); NgpMonthlyWeeklyResult result = service.query(new NgpMonthlyWeeklyRequest(null, null, null)); @@ -57,12 +57,13 @@ class NgpMonthlyWeeklyServiceTest { LocalDate.of(2026, 9, 1), LocalDate.of(2026, 9, 2), LocalDate.of(2026, 9, 3), LocalDate.of(2026, 9, 4), LocalDate.of(2026, 9, 5), LocalDate.of(2026, 9, 6), LocalDate.of(2026, 9, 7), LocalDate.of(2026, 9, 8), LocalDate.of(2026, 9, 9)); - verify(repository, times(9)).findRefreshTime(any()); + verify(repository).findRefreshTimes(LocalDate.of(2026, 9, 1), LocalDate.of(2026, 9, 9)); } @Test void buildsMondayToSundayColumnsAndStoreSubtotalsFromDailyCache() { - when(repository.findRefreshTime(any())).thenReturn(Optional.of(LocalDateTime.of(2026, 9, 9, 11, 59))); + when(repository.findRefreshTimes(any(), any())).thenReturn( + currentMonthRefreshTimes(LocalDateTime.of(2026, 9, 9, 11, 59))); when(repository.findDailyTotals(any(), any())).thenReturn(List.of( new NgpDailyStoreTotal(LocalDate.of(2026, 9, 1), "a", "网点A", 10000), new NgpDailyStoreTotal(LocalDate.of(2026, 9, 6), "a", "网点A", 20000), @@ -86,7 +87,8 @@ class NgpMonthlyWeeklyServiceTest { @Test void keepsRequestedStoreOrderAndExcludesOtherStores() { - when(repository.findRefreshTime(any())).thenReturn(Optional.of(LocalDateTime.of(2026, 9, 9, 11, 59))); + when(repository.findRefreshTimes(any(), any())).thenReturn( + currentMonthRefreshTimes(LocalDateTime.of(2026, 9, 9, 11, 59))); when(repository.findDailyTotals(any(), any())).thenReturn(List.of( new NgpDailyStoreTotal(LocalDate.of(2026, 9, 1), "网点a", "网点A", 10000), new NgpDailyStoreTotal(LocalDate.of(2026, 9, 1), "其他网点", "其他网点", 99900) @@ -106,7 +108,8 @@ class NgpMonthlyWeeklyServiceTest { @Test void acceptsCommaSeparatedStoreNameAndQueriesAllWhenItIsBlank() { - when(repository.findRefreshTime(any())).thenReturn(Optional.of(LocalDateTime.of(2026, 9, 9, 11, 59))); + when(repository.findRefreshTimes(any(), any())).thenReturn( + currentMonthRefreshTimes(LocalDateTime.of(2026, 9, 9, 11, 59))); when(repository.findDailyTotals(any(), any())).thenReturn(List.of( new NgpDailyStoreTotal(LocalDate.of(2026, 9, 1), "网点a", "网点A", 10000), new NgpDailyStoreTotal(LocalDate.of(2026, 9, 1), "网点b", "网点B", 20000), @@ -128,8 +131,8 @@ class NgpMonthlyWeeklyServiceTest { @Test void returnsStaleMonthlyCacheWhileRefreshingInBackground() { - when(repository.findRefreshTime(any())) - .thenReturn(Optional.of(LocalDateTime.of(2026, 9, 7, 12, 0))); + when(repository.findRefreshTimes(any(), any())).thenReturn( + currentMonthRefreshTimes(LocalDateTime.of(2026, 9, 7, 12, 0))); when(repository.findDailyTotals(any(), any())).thenReturn(List.of( new NgpDailyStoreTotal(LocalDate.of(2026, 9, 1), "网点a", "网点A", 12345) )); @@ -155,4 +158,11 @@ class NgpMonthlyWeeklyServiceTest { assertThat(context.getBean(NgpMonthlyWeeklyService.class)).isNotNull(); } } + + private Map currentMonthRefreshTimes(LocalDateTime refreshedAt) { + Map result = new LinkedHashMap<>(); + LocalDate.of(2026, 9, 1).datesUntil(LocalDate.of(2026, 9, 10)) + .forEach(date -> result.put(date, refreshedAt)); + return Map.copyOf(result); + } } diff --git a/src/test/java/com/company/agentfoundation/ngp/performance/NgpPerformanceCacheRepositoryTest.java b/src/test/java/com/company/agentfoundation/ngp/performance/NgpPerformanceCacheRepositoryTest.java index 3b9a8b9..e1891eb 100644 --- a/src/test/java/com/company/agentfoundation/ngp/performance/NgpPerformanceCacheRepositoryTest.java +++ b/src/test/java/com/company/agentfoundation/ngp/performance/NgpPerformanceCacheRepositoryTest.java @@ -2,6 +2,7 @@ package com.company.agentfoundation.ngp.performance; import org.junit.jupiter.api.Test; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowMapper; import java.time.LocalDate; @@ -37,4 +38,22 @@ class NgpPerformanceCacheRepositoryTest { eq(NgpPerformanceCacheRepository.FILTER_SIGNATURE) ); } + + @Test + void loadsRefreshTimesForTheWholeDateRangeInOneQuery() { + JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class); + NgpPerformanceCacheRepository repository = new NgpPerformanceCacheRepository(jdbcTemplate); + LocalDate startDate = LocalDate.of(2026, 9, 1); + LocalDate endDate = LocalDate.of(2026, 9, 24); + + repository.findRefreshTimes(startDate, endDate); + + verify(jdbcTemplate).query( + contains("business_date BETWEEN ? AND ?"), + any(RowCallbackHandler.class), + eq(startDate), + eq(endDate), + eq(NgpPerformanceCacheRepository.FILTER_SIGNATURE) + ); + } } diff --git a/src/test/java/com/company/agentfoundation/ngp/performance/NgpPerformanceTotalServiceTest.java b/src/test/java/com/company/agentfoundation/ngp/performance/NgpPerformanceTotalServiceTest.java index 3bccc82..d1ad11f 100644 --- a/src/test/java/com/company/agentfoundation/ngp/performance/NgpPerformanceTotalServiceTest.java +++ b/src/test/java/com/company/agentfoundation/ngp/performance/NgpPerformanceTotalServiceTest.java @@ -8,7 +8,6 @@ import org.junit.jupiter.api.Test; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Map; -import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -32,7 +31,7 @@ class NgpPerformanceTotalServiceTest { @Test void returnsPendingAndStartsRefreshWhenAnyDayIsMissing() { - when(repository.findRefreshTime(any())).thenReturn(Optional.empty()); + when(repository.findRefreshTimes(any(), any())).thenReturn(Map.of()); NgpPerformanceResult result = service.total(new NgpPerformanceTotalRequest( LocalDate.of(2026, 9, 1), LocalDate.of(2026, 9, 6), null)); @@ -46,7 +45,8 @@ class NgpPerformanceTotalServiceTest { @Test void returnsCachedTotalAndFiltersUniquePartialStoreName() { - when(repository.findRefreshTime(any())).thenReturn(Optional.of(LocalDateTime.now())); + when(repository.findRefreshTimes(any(), any())).thenReturn(refreshTimes( + LocalDate.of(2026, 9, 1), LocalDate.of(2026, 9, 6), LocalDateTime.now())); when(repository.aggregate(any(), any())).thenReturn(Map.of( NgpPerformanceDayLoader.normalize("兰教练(抖店)"), new NgpStoreTotal("兰教练(抖店)", 490866847L), NgpPerformanceDayLoader.normalize("另一个网点"), new NgpStoreTotal("另一个网点", 200L) @@ -63,8 +63,9 @@ class NgpPerformanceTotalServiceTest { @Test void returnsStaleCachedTotalWhileRefreshingInBackground() { - when(repository.findRefreshTime(any())) - .thenReturn(Optional.of(LocalDateTime.now().minusDays(2))); + when(repository.findRefreshTimes(any(), any())).thenReturn(refreshTimes( + LocalDate.now().minusDays(3), LocalDate.now().minusDays(2), + LocalDateTime.now().minusDays(2))); when(repository.aggregate(any(), any())).thenReturn(Map.of( NgpPerformanceDayLoader.normalize("网点A"), new NgpStoreTotal("网点A", 12345L) )); @@ -76,4 +77,14 @@ class NgpPerformanceTotalServiceTest { assertThat(((NgpPerformanceTotalResponse) result).totalAmount()).isEqualByComparingTo("123.45"); verify(coordinator).ensureRefresh(any()); } + + private Map refreshTimes( + LocalDate startDate, + LocalDate endDate, + LocalDateTime refreshedAt + ) { + Map result = new java.util.LinkedHashMap<>(); + startDate.datesUntil(endDate.plusDays(1)).forEach(date -> result.put(date, refreshedAt)); + return Map.copyOf(result); + } }