diff --git a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/StatusControllerIT.java b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/StatusControllerIT.java index eaaeac95..17eb2af9 100644 --- a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/StatusControllerIT.java +++ b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/StatusControllerIT.java @@ -1,6 +1,7 @@ package de.cotto.lndmanagej.controller; import de.cotto.lndmanagej.metrics.Metrics; +import de.cotto.lndmanagej.service.ChannelService; import de.cotto.lndmanagej.service.OwnNodeService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -8,9 +9,16 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; +import java.util.List; +import java.util.Set; + +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_TO_NODE_3; +import static org.hamcrest.core.Is.is; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; @WebMvcTest(controllers = StatusController.class) class StatusControllerIT { @@ -19,6 +27,9 @@ class StatusControllerIT { @Autowired private MockMvc mockMvc; + @MockBean + private ChannelService channelService; + @MockBean @SuppressWarnings("unused") private Metrics metrics; @@ -32,4 +43,15 @@ class StatusControllerIT { mockMvc.perform(get(PREFIX + "/synced-to-chain")) .andExpect(content().string("true")); } + + @Test + void getPubkeysForOpenChannels() throws Exception { + when(channelService.getOpenChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL_TO_NODE_3, LOCAL_OPEN_CHANNEL)); + List sortedPubkeys = List.of( + LOCAL_OPEN_CHANNEL.getRemotePubkey().toString(), + LOCAL_OPEN_CHANNEL_TO_NODE_3.getRemotePubkey().toString() + ); + mockMvc.perform(get(PREFIX + "/open-channels/pubkeys")) + .andExpect(jsonPath("$.pubkeys", is(sortedPubkeys))); + } } \ No newline at end of file diff --git a/web/src/main/java/de/cotto/lndmanagej/controller/StatusController.java b/web/src/main/java/de/cotto/lndmanagej/controller/StatusController.java index ad82b3c3..41a5bca9 100644 --- a/web/src/main/java/de/cotto/lndmanagej/controller/StatusController.java +++ b/web/src/main/java/de/cotto/lndmanagej/controller/StatusController.java @@ -2,29 +2,52 @@ package de.cotto.lndmanagej.controller; import com.codahale.metrics.MetricRegistry; import de.cotto.lndmanagej.controller.dto.ObjectMapperConfiguration; +import de.cotto.lndmanagej.controller.dto.PubkeysDto; import de.cotto.lndmanagej.metrics.Metrics; +import de.cotto.lndmanagej.model.LocalOpenChannel; +import de.cotto.lndmanagej.model.Pubkey; +import de.cotto.lndmanagej.service.ChannelService; import de.cotto.lndmanagej.service.OwnNodeService; import org.springframework.context.annotation.Import; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; +import java.util.stream.Collectors; + @RestController @RequestMapping("/api/status/") @Import(ObjectMapperConfiguration.class) public class StatusController { private final OwnNodeService ownNodeService; + private final ChannelService channelService; private final Metrics metrics; - public StatusController(OwnNodeService ownNodeService, Metrics metrics) { + public StatusController(OwnNodeService ownNodeService, ChannelService channelService, Metrics metrics) { this.ownNodeService = ownNodeService; + this.channelService = channelService; this.metrics = metrics; } @GetMapping("/synced-to-chain") public boolean isSyncedToChain() { - metrics.mark(MetricRegistry.name(getClass(), "isSyncedToChain")); + mark("isSyncedToChain"); return ownNodeService.isSyncedToChain(); } + @GetMapping("/open-channels/pubkeys") + public PubkeysDto getPubkeysForOpenChannels() { + mark("getPubkeysForOpenChannels"); + List pubkeys = channelService.getOpenChannels().stream() + .map(LocalOpenChannel::getRemotePubkey) + .sorted() + .distinct() + .collect(Collectors.toList()); + return new PubkeysDto(pubkeys); + } + + private void mark(String name) { + metrics.mark(MetricRegistry.name(getClass(), name)); + } } diff --git a/web/src/main/java/de/cotto/lndmanagej/controller/dto/PubkeysDto.java b/web/src/main/java/de/cotto/lndmanagej/controller/dto/PubkeysDto.java new file mode 100644 index 00000000..83a17265 --- /dev/null +++ b/web/src/main/java/de/cotto/lndmanagej/controller/dto/PubkeysDto.java @@ -0,0 +1,13 @@ +package de.cotto.lndmanagej.controller.dto; + +import de.cotto.lndmanagej.model.Pubkey; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +public record PubkeysDto(List pubkeys) { + public PubkeysDto(Collection pubkeys) { + this(pubkeys.stream().map(Pubkey::toString).collect(Collectors.toList())); + } +} diff --git a/web/src/test/java/de/cotto/lndmanagej/controller/StatusControllerTest.java b/web/src/test/java/de/cotto/lndmanagej/controller/StatusControllerTest.java index d2e85339..0d7e1945 100644 --- a/web/src/test/java/de/cotto/lndmanagej/controller/StatusControllerTest.java +++ b/web/src/test/java/de/cotto/lndmanagej/controller/StatusControllerTest.java @@ -1,6 +1,9 @@ package de.cotto.lndmanagej.controller; +import de.cotto.lndmanagej.controller.dto.PubkeysDto; import de.cotto.lndmanagej.metrics.Metrics; +import de.cotto.lndmanagej.model.Pubkey; +import de.cotto.lndmanagej.service.ChannelService; import de.cotto.lndmanagej.service.OwnNodeService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -8,6 +11,11 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.List; +import java.util.Set; + +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_TO_NODE_3; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.verify; @@ -24,6 +32,9 @@ class StatusControllerTest { @Mock private Metrics metrics; + @Mock + private ChannelService channelService; + @Test void isSyncedToChain() { when(ownNodeService.isSyncedToChain()).thenReturn(true); @@ -37,4 +48,13 @@ class StatusControllerTest { when(ownNodeService.isSyncedToChain()).thenReturn(false); assertThat(statusController.isSyncedToChain()).isFalse(); } + + @Test + void getPubkeysForOpenChannels() { + when(channelService.getOpenChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL_TO_NODE_3, LOCAL_OPEN_CHANNEL)); + List expectedPubkeys = + List.of(LOCAL_OPEN_CHANNEL.getRemotePubkey(), LOCAL_OPEN_CHANNEL_TO_NODE_3.getRemotePubkey()); + assertThat(statusController.getPubkeysForOpenChannels()).isEqualTo(new PubkeysDto(expectedPubkeys)); + verify(metrics).mark(argThat(name -> name.endsWith(".getPubkeysForOpenChannels"))); + } } \ No newline at end of file diff --git a/web/src/test/java/de/cotto/lndmanagej/controller/dto/PubkeysDtoTest.java b/web/src/test/java/de/cotto/lndmanagej/controller/dto/PubkeysDtoTest.java new file mode 100644 index 00000000..254be5ee --- /dev/null +++ b/web/src/test/java/de/cotto/lndmanagej/controller/dto/PubkeysDtoTest.java @@ -0,0 +1,22 @@ +package de.cotto.lndmanagej.controller.dto; + +import de.cotto.lndmanagej.model.Pubkey; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL; +import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL_TO_NODE_3; +import static org.assertj.core.api.Assertions.assertThat; + +class PubkeysDtoTest { + @Test + void uses_toString_in_order() { + List expectedPubkeys = + List.of(LOCAL_OPEN_CHANNEL.getRemotePubkey(), LOCAL_OPEN_CHANNEL_TO_NODE_3.getRemotePubkey()); + assertThat(new PubkeysDto(expectedPubkeys).pubkeys()).containsExactly( + LOCAL_OPEN_CHANNEL.getRemotePubkey().toString(), + LOCAL_OPEN_CHANNEL_TO_NODE_3.getRemotePubkey().toString() + ); + } +} \ No newline at end of file