package de.cotto.lndmanagej.service; import com.github.benmanes.caffeine.cache.LoadingCache; import de.cotto.lndmanagej.caching.CacheBuilder; import de.cotto.lndmanagej.grpc.GrpcChannels; import de.cotto.lndmanagej.grpc.GrpcClosedChannels; import de.cotto.lndmanagej.model.ChannelId; import de.cotto.lndmanagej.model.ClosedChannel; import de.cotto.lndmanagej.model.ForceClosingChannel; import de.cotto.lndmanagej.model.LocalChannel; import de.cotto.lndmanagej.model.LocalOpenChannel; import de.cotto.lndmanagej.model.Pubkey; import de.cotto.lndmanagej.model.WaitingCloseChannel; import org.springframework.stereotype.Component; import java.time.Duration; import java.util.Collection; import java.util.Optional; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @Component public class ChannelService { private static final Duration CACHE_EXPIRY = Duration.ofMinutes(1); private final GrpcChannels grpcChannels; private final LoadingCache> channelsCache; private final LoadingCache> closedChannelsCache; private final LoadingCache> forceClosingChannelsCache; private final LoadingCache> waitingCloseChannelsCache; public ChannelService(GrpcChannels grpcChannels, GrpcClosedChannels grpcClosedChannels) { this.grpcChannels = grpcChannels; channelsCache = new CacheBuilder() .withExpiry(CACHE_EXPIRY) .build(grpcChannels::getChannels); closedChannelsCache = new CacheBuilder() .withExpiry(CACHE_EXPIRY) .build(grpcClosedChannels::getClosedChannels); forceClosingChannelsCache = new CacheBuilder() .withExpiry(CACHE_EXPIRY) .build(grpcChannels::getForceClosingChannels); waitingCloseChannelsCache = new CacheBuilder() .withExpiry(CACHE_EXPIRY) .build(grpcChannels::getWaitingCloseChannels); } public boolean isClosed(ChannelId channelId) { return getClosedChannel(channelId).isPresent(); } public Optional getLocalChannel(ChannelId channelId) { return getAllLocalChannels() .filter(c -> channelId.equals(c.getId())) .findFirst(); } public Set getOpenChannels() { return channelsCache.get(""); } public Optional getOpenChannel(ChannelId channelId) { return grpcChannels.getChannel(channelId); } public Set getClosedChannels() { return closedChannelsCache.get(""); } public Optional getClosedChannel(ChannelId channelId) { return getClosedChannels().stream() .filter(c -> channelId.equals(c.getId())) .findFirst(); } public Set getForceClosingChannels() { return forceClosingChannelsCache.get(""); } public Optional getForceClosingChannel(ChannelId channelId) { return getForceClosingChannels().stream() .filter(c -> channelId.equals(c.getId())) .findFirst(); } public Set getWaitingCloseChannels() { return waitingCloseChannelsCache.get(""); } public Set getOpenChannelsWith(Pubkey peer) { return getOpenChannels().stream() .filter(c -> peer.equals(c.getRemotePubkey())) .collect(Collectors.toSet()); } public Set getClosedChannelsWith(Pubkey peer) { return getClosedChannels().stream() .filter(c -> peer.equals(c.getRemotePubkey())) .collect(Collectors.toSet()); } public Set getWaitingCloseChannelsFor(Pubkey peer) { return getWaitingCloseChannels().stream() .filter(c -> peer.equals(c.getRemotePubkey())) .collect(Collectors.toSet()); } public Set getForceClosingChannelsFor(Pubkey peer) { return getForceClosingChannels().stream() .filter(c -> peer.equals(c.getRemotePubkey())) .collect(Collectors.toSet()); } public Set getAllChannelsWith(Pubkey peer) { return getAllLocalChannels() .filter(c -> peer.equals(c.getRemotePubkey())) .collect(Collectors.toSet()); } public Stream getAllLocalChannels() { Supplier> openChannels = this::getOpenChannels; Supplier> closedChannels = this::getClosedChannels; Supplier> waitingCloseChannels = this::getWaitingCloseChannels; Supplier> forceClosingChannels = this::getForceClosingChannels; return Stream.of( openChannels, closedChannels, waitingCloseChannels, forceClosingChannels ).map(Supplier::get).flatMap(Collection::stream); } }