From 7ab9d57a59eb3a462eb54322cedc6ae748644f38 Mon Sep 17 00:00:00 2001 From: 109an <109an94@gmail.com> Date: Wed, 11 Jun 2025 17:55:58 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20realitybot=20=EC=B4=88=EA=B8=B0=20?= =?UTF-8?q?=EC=9E=91=EB=8F=99=20=EC=9D=B4=EC=8A=88=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit issue: #147 --- .../coin/realitybot/api/ApiScheduler.java | 3 +-- .../realitybot/api/UnitPriceRefresher.java | 21 +------------------ .../realitybot/config/SchedulerConfig.java | 19 +++++++++++++++-- .../trade/application/TradeQueueManager.java | 2 -- 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/cleanengine/coin/realitybot/api/ApiScheduler.java b/src/main/java/com/cleanengine/coin/realitybot/api/ApiScheduler.java index 345806a7..e55a2059 100644 --- a/src/main/java/com/cleanengine/coin/realitybot/api/ApiScheduler.java +++ b/src/main/java/com/cleanengine/coin/realitybot/api/ApiScheduler.java @@ -13,7 +13,6 @@ import io.micrometer.core.instrument.Timer; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.List; @@ -37,7 +36,7 @@ public class ApiScheduler { private final MeterRegistry meterRegistry; private String ticker; - @Scheduled(fixedRate = 5000) +// @Scheduled(fixedRate = 5000) public void MarketAllRequest() throws InterruptedException { Timer timer = meterRegistry.timer("apischeduler.request.duration"); timer.record(() -> { diff --git a/src/main/java/com/cleanengine/coin/realitybot/api/UnitPriceRefresher.java b/src/main/java/com/cleanengine/coin/realitybot/api/UnitPriceRefresher.java index eafe3a3a..e50a1384 100644 --- a/src/main/java/com/cleanengine/coin/realitybot/api/UnitPriceRefresher.java +++ b/src/main/java/com/cleanengine/coin/realitybot/api/UnitPriceRefresher.java @@ -7,9 +7,6 @@ import com.cleanengine.coin.realitybot.vo.UnitPricePolicy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.List; @@ -19,19 +16,13 @@ @Slf4j @Component @RequiredArgsConstructor -public class UnitPriceRefresher implements ApplicationRunner { +public class UnitPriceRefresher { private final UnitPricePolicy unitPricePolicy; private final AssetRepository assetRepository; private final BithumbAPIClient bithumbAPIClient; private final OpeningPriceParser openingPriceParser; private final Map unitPriceCache = new ConcurrentHashMap<>(); - @Override - public void run(ApplicationArguments args){ - log.info("Running Unit Price Refresher..."); - initializeUnitPrices(); - } - public void initializeUnitPrices() { List tickers = assetRepository.findAll(); for (Asset ticker : tickers){ @@ -40,16 +31,6 @@ public void initializeUnitPrices() { } } - @Scheduled(cron = "${bot-handler.corn}") - public void refreshUnitPrices() { - initializeUnitPrices(); -// List tickers = assetRepository.findAll(); -// for (Asset ticker : tickers){ -// double unitPrice = fetchOpeningPriceFromAPI(ticker.getTicker()); -// unitPriceCache.put(ticker.getTicker(),unitPrice); -// } - - } private double fetchOpeningPriceFromAPI(String ticker) { String rawJson = bithumbAPIClient.getOpeningPrice(ticker); //api raw데이터 diff --git a/src/main/java/com/cleanengine/coin/realitybot/config/SchedulerConfig.java b/src/main/java/com/cleanengine/coin/realitybot/config/SchedulerConfig.java index c26118a1..fad066c3 100644 --- a/src/main/java/com/cleanengine/coin/realitybot/config/SchedulerConfig.java +++ b/src/main/java/com/cleanengine/coin/realitybot/config/SchedulerConfig.java @@ -1,6 +1,7 @@ package com.cleanengine.coin.realitybot.config; import com.cleanengine.coin.realitybot.api.ApiScheduler; +import com.cleanengine.coin.realitybot.api.UnitPriceRefresher; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; @@ -18,17 +19,31 @@ public class SchedulerConfig implements SchedulingConfigurer { // @Autowired // private TaskScheduler apiScheduler; private final ApiScheduler apiScheduler; + private final UnitPriceRefresher unitPriceRefresher; + @Value("${bot-handler.corn}") + private final String corn; @Value("${bot-handler.fixed-rate}") private final Duration fixedRate; - protected SchedulerConfig(ApiScheduler apiScheduler, @Value("${bot-handler.fixed-rate}") Duration fixedRate) { + protected SchedulerConfig(ApiScheduler apiScheduler, @Value("${bot-handler.fixed-rate}") Duration fixedRate, UnitPriceRefresher unitPriceRefresher, + @Value("${bot-handler.corn}")String corn) { this.apiScheduler = apiScheduler; this.fixedRate = fixedRate; + this.unitPriceRefresher = unitPriceRefresher; + this.corn = corn; } @Override public void configureTasks(ScheduledTaskRegistrar registrar) { -// registrar.setScheduler(apiScheduler); //멀티 쓰레드 x + unitPriceRefresher.initializeUnitPrices(); //선반영 + + registrar.addCronTask(() -> { + try { + unitPriceRefresher.initializeUnitPrices(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }, corn); registrar.addFixedRateTask(() -> { try { apiScheduler.MarketAllRequest(); diff --git a/src/main/java/com/cleanengine/coin/trade/application/TradeQueueManager.java b/src/main/java/com/cleanengine/coin/trade/application/TradeQueueManager.java index 0b198e55..29e564ff 100644 --- a/src/main/java/com/cleanengine/coin/trade/application/TradeQueueManager.java +++ b/src/main/java/com/cleanengine/coin/trade/application/TradeQueueManager.java @@ -3,9 +3,7 @@ import com.cleanengine.coin.order.application.event.OrderInsertedToQueue; import lombok.extern.slf4j.Slf4j; import org.springframework.context.event.EventListener; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import org.springframework.transaction.event.TransactionalEventListener; @Slf4j @Component From c84999ac6aede1930ab47275ab2bdde770de8897 Mon Sep 17 00:00:00 2001 From: 109an <109an94@gmail.com> Date: Wed, 11 Jun 2025 17:59:21 +0900 Subject: [PATCH 2/5] =?UTF-8?q?test:=20schedulerconfig=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../realitybot/RealitybotCoreTestSuite.java | 6 -- .../realitybot/api/RefresherRunnerTest.java | 45 ---------- .../api/UnitPriceRefresherTest.java | 60 -------------- .../config/SchedulerConfigTest.java | 82 ------------------- 4 files changed, 193 deletions(-) delete mode 100644 src/test/java/com/cleanengine/coin/realitybot/api/RefresherRunnerTest.java delete mode 100644 src/test/java/com/cleanengine/coin/realitybot/api/UnitPriceRefresherTest.java delete mode 100644 src/test/java/com/cleanengine/coin/realitybot/config/SchedulerConfigTest.java diff --git a/src/test/java/com/cleanengine/coin/realitybot/RealitybotCoreTestSuite.java b/src/test/java/com/cleanengine/coin/realitybot/RealitybotCoreTestSuite.java index 74bad746..57fde90d 100644 --- a/src/test/java/com/cleanengine/coin/realitybot/RealitybotCoreTestSuite.java +++ b/src/test/java/com/cleanengine/coin/realitybot/RealitybotCoreTestSuite.java @@ -2,10 +2,7 @@ import com.cleanengine.coin.realitybot.api.ApiSchedulerTest; import com.cleanengine.coin.realitybot.api.BithumbAPIClientTest; -import com.cleanengine.coin.realitybot.api.RefresherRunnerTest; -import com.cleanengine.coin.realitybot.api.UnitPriceRefresherTest; import com.cleanengine.coin.realitybot.config.ApiClientConfigTest; -import com.cleanengine.coin.realitybot.config.SchedulerConfigTest; import com.cleanengine.coin.realitybot.domain.APIVWAPStateTest; import com.cleanengine.coin.realitybot.domain.PlatformVWAPStateTest; import com.cleanengine.coin.realitybot.domain.VWAPCalculatorTest; @@ -24,13 +21,10 @@ @Suite @SelectClasses({ - RefresherRunnerTest.class, BithumbAPIClientTest.class, - UnitPriceRefresherTest.class, OpeningPriceTest.class, PlatformVWAPStateTest.class, UnitPricePolicyTest.class, - SchedulerConfigTest.class, ApiSchedulerTest.class, ApiClientConfigTest.class, PlatformVWAPServiceTest.class, diff --git a/src/test/java/com/cleanengine/coin/realitybot/api/RefresherRunnerTest.java b/src/test/java/com/cleanengine/coin/realitybot/api/RefresherRunnerTest.java deleted file mode 100644 index ef27e0bc..00000000 --- a/src/test/java/com/cleanengine/coin/realitybot/api/RefresherRunnerTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.cleanengine.coin.realitybot.api; - -import com.cleanengine.coin.order.adapter.out.persistentce.asset.AssetRepository; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.boot.ApplicationArguments; - -import java.util.Collections; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -public class RefresherRunnerTest { - - @Spy - @InjectMocks - private UnitPriceRefresher unitPriceRefresher; - @Mock - private AssetRepository assetRepository; - @Mock - private ApplicationArguments applicationArguments; - - @BeforeEach - public void setUp(){ - when(assetRepository.findAll()).thenReturn(Collections.emptyList()); - } - - @DisplayName("어플리케이션 실행 시 호가 단위 수집") - @Test - public void runwithrefrecher() { - unitPriceRefresher.run(applicationArguments); - - verify(unitPriceRefresher,times(1)).run(any(ApplicationArguments.class)); - verify(unitPriceRefresher,times(1)).initializeUnitPrices(); - } - -// @DisplayName(" ") -} diff --git a/src/test/java/com/cleanengine/coin/realitybot/api/UnitPriceRefresherTest.java b/src/test/java/com/cleanengine/coin/realitybot/api/UnitPriceRefresherTest.java deleted file mode 100644 index 38fcb970..00000000 --- a/src/test/java/com/cleanengine/coin/realitybot/api/UnitPriceRefresherTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.cleanengine.coin.realitybot.api; - -import com.cleanengine.coin.order.adapter.out.persistentce.asset.AssetRepository; -import com.cleanengine.coin.order.domain.Asset; -import com.cleanengine.coin.realitybot.dto.OpeningPrice; -import com.cleanengine.coin.realitybot.parser.OpeningPriceParser; -import com.cleanengine.coin.realitybot.vo.UnitPricePolicy; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -public class UnitPriceRefresherTest { - @InjectMocks - private UnitPriceRefresher unitPriceRefresher; - - @Mock - private AssetRepository assetRepository; - - @Mock - private BithumbAPIClient bithumbAPIClient; - - @Mock - private OpeningPriceParser openingPriceParser; - - @Mock - private UnitPricePolicy unitPricePolicy; - - @DisplayName("run 시작시 호가 단위를 불러오는 지 여부") - @Test - void testRefresherUnitPrice() { - //given - String ticker = "BTC"; - Asset btc = new Asset(ticker,"비트코인",null); - - String json = "[{\"market\": \"KRW-BTC\", \"opening_price\": 1000000, \"trade_price\": 1010000}]"; - OpeningPrice parsed = new OpeningPrice(); - parsed.setOpening_price(1000000); - - when(assetRepository.findAll()).thenReturn(List.of(btc)); - when(bithumbAPIClient.getOpeningPrice(ticker)).thenReturn(json); - when(openingPriceParser.parseGson(json)).thenReturn(parsed); - when(unitPricePolicy.getUnitPrice(1000000)).thenReturn(100.0); - //when - unitPriceRefresher.refreshUnitPrices(); - - //then - double unitPrice = unitPriceRefresher.getUnitPriceByTicker(ticker); - assertEquals(100.0, unitPrice); - } - -} \ No newline at end of file diff --git a/src/test/java/com/cleanengine/coin/realitybot/config/SchedulerConfigTest.java b/src/test/java/com/cleanengine/coin/realitybot/config/SchedulerConfigTest.java deleted file mode 100644 index 3b573a5a..00000000 --- a/src/test/java/com/cleanengine/coin/realitybot/config/SchedulerConfigTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.cleanengine.coin.realitybot.config; - -import com.cleanengine.coin.realitybot.api.ApiScheduler; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; - -import java.time.Duration; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; - -@ExtendWith(MockitoExtension.class) -public class SchedulerConfigTest { - - @Mock - ApiScheduler apiScheduler; - - @Mock - ScheduledTaskRegistrar scheduledTaskRegistrar; - - @InjectMocks - SchedulerConfig schedulerConfig; - - @BeforeEach - void setUp() { - schedulerConfig = new SchedulerConfig(apiScheduler,Duration.ofMillis(500)); - } - - - @DisplayName("fixedrate를 적용 후 정상 작동하는 지") - @Test - void testConfigureTasksOnFixedRate() throws InterruptedException { - //when - schedulerConfig.configureTasks(scheduledTaskRegistrar); - - //then - ArgumentCaptor taskCaptor = ArgumentCaptor.forClass(Runnable.class);//스케줄러에 등록된 작업 - ArgumentCaptor intervalCaptor = ArgumentCaptor.forClass(Duration.class);//실행 주기 - //mock에게 전달 된 인자를 캡처해서 확인가능하게 해줌 - //내부 속성을 확인할 때, 동적으로 생성된 값을 검증 할 때 - - verify(scheduledTaskRegistrar).addFixedRateTask(taskCaptor.capture(), intervalCaptor.capture()); - //addFixedRateTask를 실행 시 인자 두개를 캡쳐함 - - Runnable task = taskCaptor.getValue(); - //그 캡처된 인자중 task는 실제 실행하는 작업 (schedulerconfig에 구현한 것 -> apiScheduler.MarketAllRequest();) - task.run(); //가져와서 동적으로 실행할 수 있게 됨 -> apiScheduler.MarketAllRequest(); - - verify(apiScheduler).MarketAllRequest(); //작동 검증 - - Duration interval = intervalCaptor.getValue(); - assertEquals(Duration.ofMillis(500), interval); - } - @DisplayName("marketallrequest가 예외 발생 시 에러를 던지는 지 확인") - @Test - void testCheckErrorbyMarketallRequest() throws InterruptedException { - //given - doThrow(new InterruptedException()).when(apiScheduler).MarketAllRequest(); - //메서드 실행 시 에러 던지도록 셋팅 - - //when - schedulerConfig.configureTasks(scheduledTaskRegistrar); - - //then - ArgumentCaptor taskCaptor = ArgumentCaptor.forClass(Runnable.class);//스케줄러에 등록된 작업 - verify(scheduledTaskRegistrar).addFixedRateTask(taskCaptor.capture(), any(Duration.class)); - - Runnable task = taskCaptor.getValue(); - assertThrows(RuntimeException.class, () -> task.run()); - } - -} \ No newline at end of file From 44c2e2af1d1fc227f9407b096cdc463f8af62392 Mon Sep 17 00:00:00 2001 From: 109an94 <109an94@gmail.com> Date: Wed, 11 Jun 2025 22:24:11 +0900 Subject: [PATCH 3/5] =?UTF-8?q?rename:=20=EC=98=A5=EC=88=98=EC=88=98=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coin/realitybot/config/SchedulerConfig.java | 10 +++++----- src/main/resources/application.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/cleanengine/coin/realitybot/config/SchedulerConfig.java b/src/main/java/com/cleanengine/coin/realitybot/config/SchedulerConfig.java index fad066c3..86aa2a3a 100644 --- a/src/main/java/com/cleanengine/coin/realitybot/config/SchedulerConfig.java +++ b/src/main/java/com/cleanengine/coin/realitybot/config/SchedulerConfig.java @@ -20,17 +20,17 @@ public class SchedulerConfig implements SchedulingConfigurer { // private TaskScheduler apiScheduler; private final ApiScheduler apiScheduler; private final UnitPriceRefresher unitPriceRefresher; - @Value("${bot-handler.corn}") - private final String corn; + @Value("${bot-handler.cron}") + private final String cron; @Value("${bot-handler.fixed-rate}") private final Duration fixedRate; protected SchedulerConfig(ApiScheduler apiScheduler, @Value("${bot-handler.fixed-rate}") Duration fixedRate, UnitPriceRefresher unitPriceRefresher, - @Value("${bot-handler.corn}")String corn) { + @Value("${bot-handler.cron}")String cron) { this.apiScheduler = apiScheduler; this.fixedRate = fixedRate; this.unitPriceRefresher = unitPriceRefresher; - this.corn = corn; + this.cron = cron; } @Override @@ -43,7 +43,7 @@ public void configureTasks(ScheduledTaskRegistrar registrar) { } catch (Exception e) { throw new RuntimeException(e); } - }, corn); + }, cron); registrar.addFixedRateTask(() -> { try { apiScheduler.MarketAllRequest(); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c67b4de9..e7402301 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -47,5 +47,5 @@ server: bot-handler: fixed-rate: 5000 # 5초마다 실행 - corn : "0 0 0 * * *" # 매일 자정마다 호가 + cron : "0 0 0 * * *" # 매일 자정마다 호가 order-level : 1,2,3,4,5 #오더북 단계 설정 - 주문량 증가 From e1b9584776509c02b6221ae15a84799dd21632a8 Mon Sep 17 00:00:00 2001 From: 109an94 <109an94@gmail.com> Date: Wed, 11 Jun 2025 22:51:54 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20h2=ED=99=98=EA=B2=BD=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=20=EC=8B=9C=20NPE=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../realitybot/api/H2UnitPriceRefresher.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/com/cleanengine/coin/realitybot/api/H2UnitPriceRefresher.java diff --git a/src/main/java/com/cleanengine/coin/realitybot/api/H2UnitPriceRefresher.java b/src/main/java/com/cleanengine/coin/realitybot/api/H2UnitPriceRefresher.java new file mode 100644 index 00000000..2f010ad2 --- /dev/null +++ b/src/main/java/com/cleanengine/coin/realitybot/api/H2UnitPriceRefresher.java @@ -0,0 +1,32 @@ +package com.cleanengine.coin.realitybot.api; + +import com.cleanengine.coin.order.adapter.out.persistentce.asset.AssetRepository; +import com.cleanengine.coin.order.domain.Asset; +import com.cleanengine.coin.realitybot.dto.OpeningPrice; +import com.cleanengine.coin.realitybot.parser.OpeningPriceParser; +import com.cleanengine.coin.realitybot.vo.UnitPricePolicy; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Slf4j +@Component +@Profile("h2-mem") +@RequiredArgsConstructor +public class H2UnitPriceRefresher implements ApplicationRunner { + private final UnitPriceRefresher unitPriceRefresher; + + public void run(ApplicationArguments args){ + log.info("Running Unit Price Refresher (h2-mem)..."); + unitPriceRefresher.initializeUnitPrices(); + } + +} From 38d2f8ae253d7de35ead55ca5d29007178a95f53 Mon Sep 17 00:00:00 2001 From: 109an94 <109an94@gmail.com> Date: Wed, 11 Jun 2025 22:52:46 +0900 Subject: [PATCH 5/5] =?UTF-8?q?add:=20=EC=A3=BC=EC=84=9D=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coin/realitybot/api/H2UnitPriceRefresher.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/java/com/cleanengine/coin/realitybot/api/H2UnitPriceRefresher.java b/src/main/java/com/cleanengine/coin/realitybot/api/H2UnitPriceRefresher.java index 2f010ad2..74c08104 100644 --- a/src/main/java/com/cleanengine/coin/realitybot/api/H2UnitPriceRefresher.java +++ b/src/main/java/com/cleanengine/coin/realitybot/api/H2UnitPriceRefresher.java @@ -1,22 +1,13 @@ package com.cleanengine.coin.realitybot.api; -import com.cleanengine.coin.order.adapter.out.persistentce.asset.AssetRepository; -import com.cleanengine.coin.order.domain.Asset; -import com.cleanengine.coin.realitybot.dto.OpeningPrice; -import com.cleanengine.coin.realitybot.parser.OpeningPriceParser; -import com.cleanengine.coin.realitybot.vo.UnitPricePolicy; + import lombok.RequiredArgsConstructor; -import lombok.Value; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - @Slf4j @Component @Profile("h2-mem")