mirror of
https://github.com/aljazceru/lnd-manageJ.git
synced 2026-01-19 22:14:27 +01:00
add online report
This commit is contained in:
@@ -7,8 +7,9 @@ dependencies {
|
||||
implementation project(':forwarding-history')
|
||||
implementation project(':grpc-adapter')
|
||||
implementation project(':model')
|
||||
implementation project(':transactions')
|
||||
implementation project(':onlinepeers')
|
||||
implementation project(':selfpayments')
|
||||
implementation project(':transactions')
|
||||
testImplementation testFixtures(project(':model'))
|
||||
testImplementation testFixtures(project(':transactions'))
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import de.cotto.lndmanagej.model.FeeReport;
|
||||
import de.cotto.lndmanagej.model.Node;
|
||||
import de.cotto.lndmanagej.model.NodeDetails;
|
||||
import de.cotto.lndmanagej.model.OnChainCosts;
|
||||
import de.cotto.lndmanagej.model.OnlineReport;
|
||||
import de.cotto.lndmanagej.model.Pubkey;
|
||||
import de.cotto.lndmanagej.model.RebalanceReport;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -24,6 +25,7 @@ public class NodeDetailsService {
|
||||
private final BalanceService balanceService;
|
||||
private final FeeService feeService;
|
||||
private final RebalanceService rebalanceService;
|
||||
private final OnlinePeersService onlinePeersService;
|
||||
|
||||
public NodeDetailsService(
|
||||
ChannelService channelService,
|
||||
@@ -31,7 +33,8 @@ public class NodeDetailsService {
|
||||
OnChainCostService onChainCostService,
|
||||
BalanceService balanceService,
|
||||
FeeService feeService,
|
||||
RebalanceService rebalanceService
|
||||
RebalanceService rebalanceService,
|
||||
OnlinePeersService onlinePeersService
|
||||
) {
|
||||
this.channelService = channelService;
|
||||
this.nodeService = nodeService;
|
||||
@@ -39,10 +42,12 @@ public class NodeDetailsService {
|
||||
this.balanceService = balanceService;
|
||||
this.feeService = feeService;
|
||||
this.rebalanceService = rebalanceService;
|
||||
this.onlinePeersService = onlinePeersService;
|
||||
}
|
||||
|
||||
public NodeDetails getDetails(Pubkey pubkey) {
|
||||
CompletableFuture<Node> node = getNode(pubkey);
|
||||
CompletableFuture<OnlineReport> onlineReport = node.thenApply(onlinePeersService::getOnlineReport);
|
||||
CompletableFuture<OnChainCosts> onChainCosts = getOnChainCosts(pubkey);
|
||||
CompletableFuture<BalanceInformation> balanceInformation = getBalanceInformation(pubkey);
|
||||
CompletableFuture<FeeReport> feeReport = getFeeReport(pubkey);
|
||||
@@ -65,7 +70,7 @@ public class NodeDetailsService {
|
||||
forceClosingChannelIds,
|
||||
onChainCosts.get(),
|
||||
balanceInformation.get(),
|
||||
node.get().online(),
|
||||
onlineReport.get(),
|
||||
feeReport.get(),
|
||||
rebalanceReport.get()
|
||||
);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.cotto.lndmanagej.service;
|
||||
|
||||
import de.cotto.lndmanagej.model.Node;
|
||||
import de.cotto.lndmanagej.model.OnlineReport;
|
||||
import de.cotto.lndmanagej.model.OnlineStatus;
|
||||
import de.cotto.lndmanagej.onlinepeers.OnlinePeersDao;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
@Component
|
||||
public class OnlinePeersService {
|
||||
private final OnlinePeersDao dao;
|
||||
|
||||
public OnlinePeersService(OnlinePeersDao dao) {
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
public OnlineReport getOnlineReport(Node node) {
|
||||
boolean online = node.online();
|
||||
OnlineStatus mostRecentOnlineStatus = dao.getMostRecentOnlineStatus(node.pubkey()).orElse(null);
|
||||
if (mostRecentOnlineStatus != null && mostRecentOnlineStatus.online() == online) {
|
||||
return OnlineReport.createFromStatus(mostRecentOnlineStatus);
|
||||
}
|
||||
return new OnlineReport(online, now());
|
||||
}
|
||||
|
||||
private ZonedDateTime now() {
|
||||
return ZonedDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package de.cotto.lndmanagej.service;
|
||||
|
||||
import de.cotto.lndmanagej.model.BalanceInformation;
|
||||
import de.cotto.lndmanagej.model.FeeReport;
|
||||
import de.cotto.lndmanagej.model.NodeDetailsFixtures;
|
||||
import de.cotto.lndmanagej.model.OnChainCosts;
|
||||
import de.cotto.lndmanagej.model.RebalanceReport;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -18,9 +17,13 @@ import static de.cotto.lndmanagej.model.CoopClosedChannelFixtures.CLOSED_CHANNEL
|
||||
import static de.cotto.lndmanagej.model.FeeReportFixtures.FEE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.ForceClosingChannelFixtures.FORCE_CLOSING_CHANNEL_4;
|
||||
import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHANNEL;
|
||||
import static de.cotto.lndmanagej.model.NodeDetailsFixtures.NODE_DETAILS;
|
||||
import static de.cotto.lndmanagej.model.NodeDetailsFixtures.NODE_DETAILS_EMPTY;
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.NODE;
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.NODE_PEER;
|
||||
import static de.cotto.lndmanagej.model.OnChainCostsFixtures.ON_CHAIN_COSTS;
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.ONLINE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.ONLINE_REPORT_OFFLINE;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
|
||||
import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.WaitingCloseChannelFixtures.WAITING_CLOSE_CHANNEL_TO_NODE_3;
|
||||
@@ -50,6 +53,9 @@ class NodeDetailsServiceTest {
|
||||
@Mock
|
||||
private RebalanceService rebalanceService;
|
||||
|
||||
@Mock
|
||||
private OnlinePeersService onlinePeersService;
|
||||
|
||||
@Test
|
||||
void getDetails_no_channel() {
|
||||
when(nodeService.getNode(PUBKEY)).thenReturn(NODE);
|
||||
@@ -57,7 +63,8 @@ class NodeDetailsServiceTest {
|
||||
when(onChainCostService.getOnChainCostsForPeer(PUBKEY)).thenReturn(OnChainCosts.NONE);
|
||||
when(feeService.getFeeReportForPeer(PUBKEY)).thenReturn(FeeReport.EMPTY);
|
||||
when(rebalanceService.getReportForPeer(PUBKEY)).thenReturn(RebalanceReport.EMPTY);
|
||||
assertThat(nodeDetailsService.getDetails(PUBKEY)).isEqualTo(NodeDetailsFixtures.NODE_DETAILS_EMPTY);
|
||||
when(onlinePeersService.getOnlineReport(NODE_PEER)).thenReturn(ONLINE_REPORT_OFFLINE);
|
||||
assertThat(nodeDetailsService.getDetails(PUBKEY)).isEqualTo(NODE_DETAILS_EMPTY);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,6 +78,7 @@ class NodeDetailsServiceTest {
|
||||
when(channelService.getForceClosingChannelsWith(PUBKEY)).thenReturn(Set.of(FORCE_CLOSING_CHANNEL_4));
|
||||
when(feeService.getFeeReportForPeer(PUBKEY)).thenReturn(FEE_REPORT);
|
||||
when(rebalanceService.getReportForPeer(PUBKEY)).thenReturn(REBALANCE_REPORT);
|
||||
assertThat(nodeDetailsService.getDetails(PUBKEY)).isEqualTo(NodeDetailsFixtures.NODE_DETAILS);
|
||||
when(onlinePeersService.getOnlineReport(NODE_PEER)).thenReturn(ONLINE_REPORT);
|
||||
assertThat(nodeDetailsService.getDetails(PUBKEY)).isEqualTo(NODE_DETAILS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package de.cotto.lndmanagej.service;
|
||||
|
||||
import de.cotto.lndmanagej.model.OnlineReport;
|
||||
import de.cotto.lndmanagej.onlinepeers.OnlinePeersDao;
|
||||
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.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.NODE;
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.NODE_PEER;
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.ONLINE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.OnlineStatusFixtures.ONLINE_STATUS;
|
||||
import static de.cotto.lndmanagej.model.OnlineStatusFixtures.ONLINE_STATUS_OFFLINE;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class OnlinePeersServiceTest {
|
||||
@InjectMocks
|
||||
private OnlinePeersService onlinePeersService;
|
||||
|
||||
@Mock
|
||||
private OnlinePeersDao dao;
|
||||
|
||||
@Test
|
||||
void with_time_if_given_status_matches_last_known_status() {
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY)).thenReturn(Optional.of(ONLINE_STATUS));
|
||||
assertThat(onlinePeersService.getOnlineReport(NODE_PEER)).isEqualTo(ONLINE_REPORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void with_current_time_if_given_status_does_not_match_last_known_status() {
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY)).thenReturn(Optional.of(ONLINE_STATUS_OFFLINE));
|
||||
OnlineReport report = onlinePeersService.getOnlineReport(NODE_PEER);
|
||||
assertThat(report.online()).isTrue();
|
||||
assertVeryRecentSince(report);
|
||||
}
|
||||
|
||||
@Test
|
||||
void with_current_time_if_no_persisted_status_known() {
|
||||
OnlineReport report = onlinePeersService.getOnlineReport(NODE);
|
||||
assertThat(report.online()).isFalse();
|
||||
assertVeryRecentSince(report);
|
||||
}
|
||||
|
||||
@Test
|
||||
void with_current_state_if_no_persisted_status_known() {
|
||||
OnlineReport report = onlinePeersService.getOnlineReport(NODE_PEER);
|
||||
assertThat(report.online()).isTrue();
|
||||
assertVeryRecentSince(report);
|
||||
}
|
||||
|
||||
private void assertVeryRecentSince(OnlineReport report) {
|
||||
assertThat(report.since())
|
||||
.isAfter(ZonedDateTime.now(ZoneOffset.UTC).minusSeconds(1))
|
||||
.asString().hasSize(20);
|
||||
}
|
||||
}
|
||||
10
balances/build.gradle
Normal file
10
balances/build.gradle
Normal file
@@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
id 'lnd-manageJ.java-library-conventions'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':model')
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
testRuntimeOnly 'com.h2database:h2'
|
||||
testFixturesApi testFixtures(project(':model'))
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.balances.persistence;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
|
||||
import static de.cotto.lndmanagej.balances.BalancesFixtures.BALANCES;
|
||||
import static de.cotto.lndmanagej.balances.BalancesFixtures.BALANCES_OLD;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_2;
|
||||
import static de.cotto.lndmanagej.statistics.StatisticsFixtures.BALANCES;
|
||||
import static de.cotto.lndmanagej.statistics.StatisticsFixtures.BALANCES_OLD;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
package de.cotto.lndmanagej.balances;
|
||||
|
||||
import de.cotto.lndmanagej.model.BalanceInformation;
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
package de.cotto.lndmanagej.balances;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.balances.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.balances.Balances;
|
||||
import de.cotto.lndmanagej.balances.BalancesDao;
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.statistics.Balances;
|
||||
import de.cotto.lndmanagej.statistics.BalancesDao;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.balances.persistence;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.Serial;
|
||||
@@ -1,10 +1,10 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.balances.persistence;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import de.cotto.lndmanagej.balances.Balances;
|
||||
import de.cotto.lndmanagej.model.BalanceInformation;
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.model.Coins;
|
||||
import de.cotto.lndmanagej.statistics.Balances;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.balances.persistence;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.balances.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.statistics.StatisticsFixtures;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -10,9 +9,10 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
|
||||
import static de.cotto.lndmanagej.balances.BalancesFixtures.BALANCES;
|
||||
import static de.cotto.lndmanagej.balances.BalancesFixtures.TIMESTAMP;
|
||||
import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static de.cotto.lndmanagej.statistics.StatisticsFixtures.BALANCES;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -31,7 +31,7 @@ class BalancesDaoImplTest {
|
||||
void saveStatistics() {
|
||||
dao.saveBalances(BALANCES);
|
||||
verify(balancesRepository).save(argThat(jpaDto ->
|
||||
jpaDto.getTimestamp() == StatisticsFixtures.TIMESTAMP.toEpochSecond(ZoneOffset.UTC)
|
||||
jpaDto.getTimestamp() == TIMESTAMP.toEpochSecond(ZoneOffset.UTC)
|
||||
));
|
||||
verify(balancesRepository).save(argThat(jpaDto ->
|
||||
jpaDto.getChannelId() == CHANNEL_ID.getShortChannelId()));
|
||||
@@ -1,15 +1,14 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.balances.persistence;
|
||||
|
||||
import nl.jqno.equalsverifier.EqualsVerifier;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class BalancesIdTest {
|
||||
@Test
|
||||
void test_default_constructor() {
|
||||
// required for JPA
|
||||
assertThat(new BalancesId()).isNotNull();
|
||||
Assertions.assertThat(new BalancesId()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1,13 +1,13 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.balances.persistence;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
import static de.cotto.lndmanagej.balances.BalancesFixtures.BALANCES;
|
||||
import static de.cotto.lndmanagej.balances.BalancesFixtures.TIMESTAMP;
|
||||
import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
import static de.cotto.lndmanagej.statistics.StatisticsFixtures.BALANCES;
|
||||
import static de.cotto.lndmanagej.statistics.StatisticsFixtures.TIMESTAMP;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class BalancesJpaDtoTest {
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
package de.cotto.lndmanagej.balances;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
@@ -8,7 +8,7 @@ import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFOR
|
||||
import static de.cotto.lndmanagej.model.BalanceInformationFixtures.BALANCE_INFORMATION_2;
|
||||
import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID;
|
||||
|
||||
public class StatisticsFixtures {
|
||||
public class BalancesFixtures {
|
||||
public static final LocalDateTime TIMESTAMP = LocalDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS);
|
||||
public static final Balances BALANCES =
|
||||
new Balances(TIMESTAMP, CHANNEL_ID, BALANCE_INFORMATION);
|
||||
@@ -11,7 +11,7 @@ public record NodeDetails(
|
||||
List<ChannelId> pendingForceClosingChannels,
|
||||
OnChainCosts onChainCosts,
|
||||
BalanceInformation balanceInformation,
|
||||
boolean online,
|
||||
OnlineReport onlineReport,
|
||||
FeeReport feeReport,
|
||||
RebalanceReport rebalanceReport
|
||||
) {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public record OnlineReport(boolean online, ZonedDateTime since) {
|
||||
public static OnlineReport createFromStatus(OnlineStatus onlineStatus) {
|
||||
return new OnlineReport(onlineStatus.online(), onlineStatus.since());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public record OnlineStatus(boolean online, ZonedDateTime since) {
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import static de.cotto.lndmanagej.model.FeeReportFixtures.FEE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.NodeDetailsFixtures.NODE_DETAILS;
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS;
|
||||
import static de.cotto.lndmanagej.model.OnChainCostsFixtures.ON_CHAIN_COSTS;
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.ONLINE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
|
||||
import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -57,11 +58,12 @@ class NodeDetailsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void online() {
|
||||
assertThat(NODE_DETAILS.online()).isTrue();
|
||||
void onlineReport() {
|
||||
assertThat(NODE_DETAILS.onlineReport()).isEqualTo(ONLINE_REPORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
void feeReport() {
|
||||
assertThat(NODE_DETAILS.feeReport()).isEqualTo(FEE_REPORT);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.ONLINE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.TIMESTAMP;
|
||||
import static de.cotto.lndmanagej.model.OnlineStatusFixtures.ONLINE_STATUS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class OnlineReportTest {
|
||||
@Test
|
||||
void online() {
|
||||
assertThat(ONLINE_REPORT.online()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void since() {
|
||||
assertThat(ONLINE_REPORT.since()).isEqualTo(TIMESTAMP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createFromOnlineStatus() {
|
||||
assertThat(OnlineReport.createFromStatus(ONLINE_STATUS)).isEqualTo(ONLINE_REPORT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static de.cotto.lndmanagej.model.OnlineStatusFixtures.ONLINE_STATUS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class OnlineStatusTest {
|
||||
@Test
|
||||
void online() {
|
||||
assertThat(ONLINE_STATUS.online()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void since() {
|
||||
assertThat(ONLINE_STATUS.since())
|
||||
.isEqualTo(ZonedDateTime.of(2021, 12, 23, 1, 2, 3, 0, ZoneOffset.UTC));
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID_4;
|
||||
import static de.cotto.lndmanagej.model.FeeReportFixtures.FEE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS;
|
||||
import static de.cotto.lndmanagej.model.OnChainCostsFixtures.ON_CHAIN_COSTS;
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.ONLINE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.ONLINE_REPORT_OFFLINE;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
|
||||
import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT;
|
||||
|
||||
@@ -23,7 +25,7 @@ public class NodeDetailsFixtures {
|
||||
List.of(CHANNEL_ID_4),
|
||||
ON_CHAIN_COSTS,
|
||||
BALANCE_INFORMATION_2,
|
||||
true,
|
||||
ONLINE_REPORT,
|
||||
FEE_REPORT,
|
||||
REBALANCE_REPORT
|
||||
);
|
||||
@@ -36,7 +38,7 @@ public class NodeDetailsFixtures {
|
||||
List.of(),
|
||||
OnChainCosts.NONE,
|
||||
BalanceInformation.EMPTY,
|
||||
false,
|
||||
ONLINE_REPORT_OFFLINE,
|
||||
FeeReport.EMPTY,
|
||||
RebalanceReport.EMPTY
|
||||
);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
public class OnlineReportFixtures {
|
||||
public static final ZonedDateTime TIMESTAMP = LocalDateTime.of(2021, 12, 23, 1, 2, 3).atZone(UTC);
|
||||
public static final OnlineReport ONLINE_REPORT = new OnlineReport(true, TIMESTAMP);
|
||||
public static final OnlineReport ONLINE_REPORT_OFFLINE = new OnlineReport(false, TIMESTAMP);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.cotto.lndmanagej.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
public class OnlineStatusFixtures {
|
||||
private static final ZonedDateTime TIMESTAMP = LocalDateTime.of(2021, 12, 23, 1, 2, 3).atZone(UTC);
|
||||
|
||||
public static final OnlineStatus ONLINE_STATUS = new OnlineStatus(
|
||||
true,
|
||||
TIMESTAMP
|
||||
);
|
||||
|
||||
public static final OnlineStatus ONLINE_STATUS_OFFLINE = new OnlineStatus(
|
||||
false,
|
||||
TIMESTAMP
|
||||
);
|
||||
}
|
||||
10
onlinepeers/build.gradle
Normal file
10
onlinepeers/build.gradle
Normal file
@@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
id 'lnd-manageJ.java-library-conventions'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':model')
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
testRuntimeOnly 'com.h2database:h2'
|
||||
testFixturesApi testFixtures(project(':model'))
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.cotto.lndmanagej;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpringBootConfiguration {
|
||||
public SpringBootConfiguration() {
|
||||
// default constructor
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.onlinepeers.persistence;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2;
|
||||
@@ -13,7 +13,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
class OnlinePeersRepositoryIT {
|
||||
private static final LocalDateTime TIMESTAMP = LocalDateTime.now(ZoneOffset.UTC);
|
||||
private static final ZonedDateTime TIMESTAMP = ZonedDateTime.now(ZoneOffset.UTC);
|
||||
|
||||
@Autowired
|
||||
private OnlinePeersRepository repository;
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.cotto.lndmanagej.onlinepeers;
|
||||
|
||||
import de.cotto.lndmanagej.model.OnlineStatus;
|
||||
import de.cotto.lndmanagej.model.Pubkey;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface OnlinePeersDao {
|
||||
void saveOnlineStatus(Pubkey pubkey, boolean online, ZonedDateTime timestamp);
|
||||
|
||||
Optional<OnlineStatus> getMostRecentOnlineStatus(Pubkey pubkey);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.onlinepeers.persistence;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.Serial;
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.onlinepeers.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.model.OnlineStatus;
|
||||
import de.cotto.lndmanagej.model.Pubkey;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
@@ -9,7 +10,9 @@ import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Table;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
@Entity
|
||||
@IdClass(OnlinePeerId.class)
|
||||
@@ -30,10 +33,15 @@ public class OnlinePeerJpaDto {
|
||||
// for JPA
|
||||
}
|
||||
|
||||
public OnlinePeerJpaDto(Pubkey pubkey, boolean online, LocalDateTime timestamp) {
|
||||
public OnlinePeerJpaDto(Pubkey pubkey, boolean online, ZonedDateTime timestamp) {
|
||||
this.pubkey = pubkey.toString();
|
||||
this.online = online;
|
||||
this.timestamp = timestamp.toEpochSecond(ZoneOffset.UTC);
|
||||
this.timestamp = timestamp.toEpochSecond();
|
||||
}
|
||||
|
||||
public OnlineStatus toModel() {
|
||||
ZonedDateTime zonedDateTime = LocalDateTime.ofEpochSecond(timestamp, 0, UTC).atZone(UTC);
|
||||
return new OnlineStatus(online, zonedDateTime);
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
@@ -1,11 +1,12 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.onlinepeers.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.model.OnlineStatus;
|
||||
import de.cotto.lndmanagej.model.Pubkey;
|
||||
import de.cotto.lndmanagej.statistics.OnlinePeersDao;
|
||||
import de.cotto.lndmanagej.onlinepeers.OnlinePeersDao;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@@ -18,12 +19,12 @@ class OnlinePeersDaoImpl implements OnlinePeersDao {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveOnlineStatus(Pubkey pubkey, boolean online, LocalDateTime timestamp) {
|
||||
public void saveOnlineStatus(Pubkey pubkey, boolean online, ZonedDateTime timestamp) {
|
||||
repository.save(new OnlinePeerJpaDto(pubkey, online, timestamp));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Boolean> getMostRecentOnlineStatus(Pubkey pubkey) {
|
||||
return repository.findTopByPubkeyOrderByTimestampDesc(pubkey.toString()).map(OnlinePeerJpaDto::isOnline);
|
||||
public Optional<OnlineStatus> getMostRecentOnlineStatus(Pubkey pubkey) {
|
||||
return repository.findTopByPubkeyOrderByTimestampDesc(pubkey.toString()).map(OnlinePeerJpaDto::toModel);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.onlinepeers.persistence;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.onlinepeers.persistence;
|
||||
|
||||
import nl.jqno.equalsverifier.EqualsVerifier;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -0,0 +1,19 @@
|
||||
package de.cotto.lndmanagej.onlinepeers.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.model.OnlineStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class OnlinePeerJpaDtoTest {
|
||||
@Test
|
||||
void toModel() {
|
||||
ZonedDateTime zonedDateTime = ZonedDateTime.of(2021, 12, 23, 1, 2, 3, 0, ZoneOffset.UTC);
|
||||
OnlinePeerJpaDto onlinePeerJpaDto = new OnlinePeerJpaDto(PUBKEY, true, zonedDateTime);
|
||||
assertThat(onlinePeerJpaDto.toModel()).isEqualTo(new OnlineStatus(true, zonedDateTime));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.onlinepeers.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.model.Pubkey;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -7,11 +7,11 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static de.cotto.lndmanagej.model.OnlineStatusFixtures.ONLINE_STATUS;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -21,7 +21,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class OnlinePeersDaoImplTest {
|
||||
private static final LocalDateTime TIMESTAMP = LocalDateTime.now(ZoneOffset.UTC);
|
||||
private static final ZonedDateTime TIMESTAMP = ONLINE_STATUS.since();
|
||||
|
||||
@InjectMocks
|
||||
private OnlinePeersDaoImpl dao;
|
||||
@@ -50,7 +50,7 @@ class OnlinePeersDaoImplTest {
|
||||
void getMostRecentOnlineStatus() {
|
||||
OnlinePeerJpaDto dto = new OnlinePeerJpaDto(PUBKEY, true, TIMESTAMP);
|
||||
when(repository.findTopByPubkeyOrderByTimestampDesc(PUBKEY.toString())).thenReturn(Optional.of(dto));
|
||||
assertThat(dao.getMostRecentOnlineStatus(PUBKEY)).contains(true);
|
||||
assertThat(dao.getMostRecentOnlineStatus(PUBKEY)).contains(ONLINE_STATUS);
|
||||
}
|
||||
|
||||
private void verifySave(Pubkey pubkey, boolean expected) {
|
||||
11
privatechannels/build.gradle
Normal file
11
privatechannels/build.gradle
Normal file
@@ -0,0 +1,11 @@
|
||||
plugins {
|
||||
id 'lnd-manageJ.java-library-conventions'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':caching')
|
||||
implementation project(':model')
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
testRuntimeOnly 'com.h2database:h2'
|
||||
testFixturesApi testFixtures(project(':model'))
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.cotto.lndmanagej;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpringBootConfiguration {
|
||||
public SpringBootConfiguration() {
|
||||
// default constructor
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.privatechannels.persistence;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
package de.cotto.lndmanagej.privatechannels;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
package de.cotto.lndmanagej.privatechannels;
|
||||
|
||||
import com.codahale.metrics.annotation.Timed;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.privatechannels.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.privatechannels.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.statistics.PrivateChannelsDao;
|
||||
import de.cotto.lndmanagej.privatechannels.PrivateChannelsDao;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.privatechannels.persistence;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
package de.cotto.lndmanagej.privatechannels;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.cotto.lndmanagej.statistics.persistence;
|
||||
package de.cotto.lndmanagej.privatechannels.persistence;
|
||||
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -1,6 +1,7 @@
|
||||
rootProject.name = 'lnd-manageJ'
|
||||
include 'application'
|
||||
include 'backend'
|
||||
include 'balances'
|
||||
include 'caching'
|
||||
include 'forwarding-history'
|
||||
include 'grpc-adapter'
|
||||
@@ -8,7 +9,9 @@ include 'grpc-client'
|
||||
include 'hardcoded'
|
||||
include 'invoices'
|
||||
include 'model'
|
||||
include 'onlinepeers'
|
||||
include 'payments'
|
||||
include 'privatechannels'
|
||||
include 'selfpayments'
|
||||
include 'statistics'
|
||||
include 'transactions'
|
||||
|
||||
@@ -4,9 +4,10 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
implementation project(':backend')
|
||||
implementation project(':model')
|
||||
implementation project(':balances')
|
||||
implementation project(':caching')
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
testRuntimeOnly 'com.h2database:h2'
|
||||
implementation project(':model')
|
||||
implementation project(':onlinepeers')
|
||||
implementation project(':privatechannels')
|
||||
testFixturesApi testFixtures(project(':model'))
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
|
||||
import de.cotto.lndmanagej.balances.Balances;
|
||||
import de.cotto.lndmanagej.balances.BalancesDao;
|
||||
import de.cotto.lndmanagej.model.BalanceInformation;
|
||||
import de.cotto.lndmanagej.model.LocalOpenChannel;
|
||||
import de.cotto.lndmanagej.service.ChannelService;
|
||||
@@ -12,11 +14,11 @@ import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
public class BalanceStatisticsService {
|
||||
public class BalancesUpdater {
|
||||
private final ChannelService channelService;
|
||||
private final BalancesDao balancesDao;
|
||||
|
||||
public BalanceStatisticsService(ChannelService channelService, BalancesDao balancesDao) {
|
||||
public BalancesUpdater(ChannelService channelService, BalancesDao balancesDao) {
|
||||
this.channelService = channelService;
|
||||
this.balancesDao = balancesDao;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
|
||||
import de.cotto.lndmanagej.model.Pubkey;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface OnlinePeersDao {
|
||||
void saveOnlineStatus(Pubkey pubkey, boolean online, LocalDateTime timestamp);
|
||||
|
||||
Optional<Boolean> getMostRecentOnlineStatus(Pubkey pubkey);
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
|
||||
import de.cotto.lndmanagej.model.LocalChannel;
|
||||
import de.cotto.lndmanagej.model.Node;
|
||||
import de.cotto.lndmanagej.model.OnlineStatus;
|
||||
import de.cotto.lndmanagej.onlinepeers.OnlinePeersDao;
|
||||
import de.cotto.lndmanagej.service.ChannelService;
|
||||
import de.cotto.lndmanagej.service.NodeService;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
@@ -24,12 +28,20 @@ public class OnlinePeersUpdater {
|
||||
|
||||
@Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES)
|
||||
public void storePeerOnlineStatus() {
|
||||
LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
|
||||
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
|
||||
channelService.getOpenChannels().stream()
|
||||
.map(LocalChannel::getRemotePubkey)
|
||||
.distinct()
|
||||
.map(nodeService::getNode)
|
||||
.filter(node -> dao.getMostRecentOnlineStatus(node.pubkey()).orElse(!node.online()) != node.online())
|
||||
.filter(this::shouldUpdate)
|
||||
.forEach(node -> dao.saveOnlineStatus(node.pubkey(), node.online(), now));
|
||||
}
|
||||
|
||||
private boolean shouldUpdate(Node node) {
|
||||
Optional<OnlineStatus> mostRecentOnlineStatus = dao.getMostRecentOnlineStatus(node.pubkey());
|
||||
if (mostRecentOnlineStatus.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return mostRecentOnlineStatus.get().online() != node.online();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
|
||||
import de.cotto.lndmanagej.privatechannels.PrivateChannelsDao;
|
||||
import de.cotto.lndmanagej.service.ChannelService;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
|
||||
import de.cotto.lndmanagej.balances.Balances;
|
||||
import de.cotto.lndmanagej.balances.BalancesDao;
|
||||
import de.cotto.lndmanagej.model.ChannelId;
|
||||
import de.cotto.lndmanagej.model.LocalOpenChannel;
|
||||
import de.cotto.lndmanagej.service.ChannelService;
|
||||
@@ -26,10 +28,10 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class BalanceStatisticsServiceTest {
|
||||
class BalancesUpdaterTest {
|
||||
private static final LocalDateTime LOCAL_DATE_TIME = LocalDateTime.now(ZoneOffset.UTC);
|
||||
@InjectMocks
|
||||
private BalanceStatisticsService balanceStatisticsService;
|
||||
private BalancesUpdater balancesUpdater;
|
||||
|
||||
@Mock
|
||||
private ChannelService channelService;
|
||||
@@ -43,7 +45,7 @@ class BalanceStatisticsServiceTest {
|
||||
LOCAL_OPEN_CHANNEL,
|
||||
LOCAL_OPEN_CHANNEL_MORE_BALANCE_2
|
||||
));
|
||||
balanceStatisticsService.storeBalances();
|
||||
balancesUpdater.storeBalances();
|
||||
verify(dao).saveBalances(argThat(withBalanceInformation(LOCAL_OPEN_CHANNEL_MORE_BALANCE_2)));
|
||||
verify(dao).saveBalances(argThat(withChannelId(LOCAL_OPEN_CHANNEL_MORE_BALANCE_2)));
|
||||
verify(dao).saveBalances(argThat(withBalanceInformation(LOCAL_OPEN_CHANNEL)));
|
||||
@@ -57,7 +59,7 @@ class BalanceStatisticsServiceTest {
|
||||
ChannelId channelId = LOCAL_OPEN_CHANNEL.getId();
|
||||
Balances balances = new Balances(LOCAL_DATE_TIME, channelId, BALANCE_INFORMATION_2);
|
||||
when(dao.getMostRecentBalances(channelId)).thenReturn(Optional.of(balances));
|
||||
balanceStatisticsService.storeBalances();
|
||||
balancesUpdater.storeBalances();
|
||||
verify(dao).saveBalances(any());
|
||||
}
|
||||
|
||||
@@ -67,7 +69,7 @@ class BalanceStatisticsServiceTest {
|
||||
ChannelId channelId = LOCAL_OPEN_CHANNEL.getId();
|
||||
Balances balances = new Balances(LOCAL_DATE_TIME, channelId, LOCAL_OPEN_CHANNEL.getBalanceInformation());
|
||||
when(dao.getMostRecentBalances(channelId)).thenReturn(Optional.of(balances));
|
||||
balanceStatisticsService.storeBalances();
|
||||
balancesUpdater.storeBalances();
|
||||
verify(dao, never()).saveBalances(any());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
|
||||
import de.cotto.lndmanagej.onlinepeers.OnlinePeersDao;
|
||||
import de.cotto.lndmanagej.service.ChannelService;
|
||||
import de.cotto.lndmanagej.service.NodeService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -17,6 +18,8 @@ import static de.cotto.lndmanagej.model.LocalOpenChannelFixtures.LOCAL_OPEN_CHAN
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.NODE_2;
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.NODE_2_PEER;
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.NODE_3_PEER;
|
||||
import static de.cotto.lndmanagej.model.OnlineStatusFixtures.ONLINE_STATUS;
|
||||
import static de.cotto.lndmanagej.model.OnlineStatusFixtures.ONLINE_STATUS_OFFLINE;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -65,7 +68,7 @@ class OnlinePeersUpdaterTest {
|
||||
|
||||
@Test
|
||||
void saveOnlineStatus_online_to_offline() {
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY_2)).thenReturn(Optional.of(true));
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY_2)).thenReturn(Optional.of(ONLINE_STATUS));
|
||||
when(nodeService.getNode(PUBKEY_2)).thenReturn(NODE_2);
|
||||
|
||||
onlinePeersUpdater.storePeerOnlineStatus();
|
||||
@@ -75,7 +78,7 @@ class OnlinePeersUpdaterTest {
|
||||
|
||||
@Test
|
||||
void saveOnlineStatus_offline_to_online() {
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY_2)).thenReturn(Optional.of(false));
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY_2)).thenReturn(Optional.of(ONLINE_STATUS_OFFLINE));
|
||||
when(nodeService.getNode(PUBKEY_2)).thenReturn(NODE_2_PEER);
|
||||
|
||||
onlinePeersUpdater.storePeerOnlineStatus();
|
||||
@@ -85,7 +88,7 @@ class OnlinePeersUpdaterTest {
|
||||
|
||||
@Test
|
||||
void saveOnlineStatus_still_offline() {
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY_2)).thenReturn(Optional.of(false));
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY_2)).thenReturn(Optional.of(ONLINE_STATUS_OFFLINE));
|
||||
when(nodeService.getNode(PUBKEY_2)).thenReturn(NODE_2);
|
||||
|
||||
onlinePeersUpdater.storePeerOnlineStatus();
|
||||
@@ -95,7 +98,7 @@ class OnlinePeersUpdaterTest {
|
||||
|
||||
@Test
|
||||
void saveOnlineStatus_still_online() {
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY_2)).thenReturn(Optional.of(true));
|
||||
when(dao.getMostRecentOnlineStatus(PUBKEY_2)).thenReturn(Optional.of(ONLINE_STATUS));
|
||||
when(nodeService.getNode(PUBKEY_2)).thenReturn(NODE_2_PEER);
|
||||
|
||||
onlinePeersUpdater.storePeerOnlineStatus();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.cotto.lndmanagej.statistics;
|
||||
|
||||
import de.cotto.lndmanagej.privatechannels.PrivateChannelsDao;
|
||||
import de.cotto.lndmanagej.service.ChannelService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
@@ -100,7 +100,8 @@ class NodeControllerIT {
|
||||
.andExpect(jsonPath("$.onChainCosts.openCosts", is("1000")))
|
||||
.andExpect(jsonPath("$.onChainCosts.closeCosts", is("2000")))
|
||||
.andExpect(jsonPath("$.onChainCosts.sweepCosts", is("3000")))
|
||||
.andExpect(jsonPath("$.online", is(true)));
|
||||
.andExpect(jsonPath("$.onlineReport.online", is(true)))
|
||||
.andExpect(jsonPath("$.onlineReport.since", is("2021-12-23T01:02:03Z")));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,9 +15,7 @@ public record ClosedChannelDetailsDto(String initiator, int height, boolean forc
|
||||
}
|
||||
|
||||
public static ClosedChannelDetailsDto createFromModel(LocalChannel localChannel) {
|
||||
boolean closed = localChannel instanceof ClosedChannel;
|
||||
if (closed) {
|
||||
ClosedChannel closedChannel = (ClosedChannel) localChannel;
|
||||
if (localChannel instanceof ClosedChannel closedChannel) {
|
||||
boolean forceClosed = closedChannel instanceof ForceClosedChannel;
|
||||
boolean breach = forceClosed && closedChannel instanceof BreachForceClosedChannel;
|
||||
return new ClosedChannelDetailsDto(
|
||||
|
||||
@@ -17,7 +17,7 @@ public record NodeDetailsDto(
|
||||
List<ChannelId> pendingForceClosingChannels,
|
||||
OnChainCostsDto onChainCosts,
|
||||
BalanceInformationDto balance,
|
||||
boolean online,
|
||||
OnlineReportDto onlineReport,
|
||||
FeeReportDto feeReport,
|
||||
RebalanceReportDto rebalanceReport
|
||||
) {
|
||||
@@ -31,7 +31,7 @@ public record NodeDetailsDto(
|
||||
nodeDetails.pendingForceClosingChannels(),
|
||||
OnChainCostsDto.createFromModel(nodeDetails.onChainCosts()),
|
||||
BalanceInformationDto.createFromModel(nodeDetails.balanceInformation()),
|
||||
nodeDetails.online(),
|
||||
OnlineReportDto.createFromModel(nodeDetails.onlineReport()),
|
||||
FeeReportDto.createFromModel(nodeDetails.feeReport()),
|
||||
RebalanceReportDto.createFromModel(nodeDetails.rebalanceReport())
|
||||
);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.cotto.lndmanagej.controller.dto;
|
||||
|
||||
import de.cotto.lndmanagej.model.OnlineReport;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public record OnlineReportDto(boolean online, String since) {
|
||||
public static OnlineReportDto createFromModel(OnlineReport onlineReport) {
|
||||
String formattedDateTime = onlineReport.since().format(DateTimeFormatter.ISO_INSTANT);
|
||||
return new OnlineReportDto(onlineReport.online(), formattedDateTime);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import static de.cotto.lndmanagej.model.FeeReportFixtures.FEE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.NodeDetailsFixtures.NODE_DETAILS;
|
||||
import static de.cotto.lndmanagej.model.NodeFixtures.ALIAS;
|
||||
import static de.cotto.lndmanagej.model.OnChainCostsFixtures.ON_CHAIN_COSTS;
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.ONLINE_REPORT;
|
||||
import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY;
|
||||
import static de.cotto.lndmanagej.model.RebalanceReportFixtures.REBALANCE_REPORT;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -29,7 +30,7 @@ class NodeDetailsDtoTest {
|
||||
List.of(CHANNEL_ID_4),
|
||||
OnChainCostsDto.createFromModel(ON_CHAIN_COSTS),
|
||||
BalanceInformationDto.createFromModel(BALANCE_INFORMATION_2),
|
||||
true,
|
||||
OnlineReportDto.createFromModel(ONLINE_REPORT),
|
||||
FeeReportDto.createFromModel(FEE_REPORT),
|
||||
RebalanceReportDto.createFromModel(REBALANCE_REPORT)
|
||||
);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.cotto.lndmanagej.controller.dto;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static de.cotto.lndmanagej.model.OnlineReportFixtures.ONLINE_REPORT;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class OnlineReportDtoTest {
|
||||
@Test
|
||||
void createFromModel() {
|
||||
assertThat(OnlineReportDto.createFromModel(ONLINE_REPORT)).isEqualTo(
|
||||
new OnlineReportDto(ONLINE_REPORT.online(), ONLINE_REPORT.since().toString())
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void since() {
|
||||
assertThat(OnlineReportDto.createFromModel(ONLINE_REPORT).since()).isEqualTo("2021-12-23T01:02:03Z");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user