Skip to content

Commit

Permalink
Revert "Introduce FullClient"
Browse files Browse the repository at this point in the history
  • Loading branch information
David-Petrov authored Nov 24, 2023
1 parent 7743804 commit 1a15dd3
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 143 deletions.
50 changes: 3 additions & 47 deletions src/main/java/com/limechain/Main.java
Original file line number Diff line number Diff line change
@@ -1,59 +1,15 @@
package com.limechain;

import com.limechain.config.HostConfig;
import com.limechain.client.FullNode;
import com.limechain.client.LightClient;
import com.limechain.client.HostNode;
import com.limechain.network.protocol.blockannounce.NodeRole;
import com.limechain.rpc.server.AppBean;
import com.limechain.lightclient.LightClient;
import com.limechain.rpc.server.RpcApp;
import lombok.extern.java.Log;
import sun.misc.Signal;

import java.util.logging.Level;

@Log
public class Main {

public static void main(String[] args) {
// Instantiate and start the spring application, so we get the global context
RpcApp rpcApp = new RpcApp();
rpcApp.start(args);

// Figure out what client role we want to start
HostConfig hostConfig = AppBean.getBean(HostConfig.class);
final NodeRole nodeRole = hostConfig.getNodeRole();
HostNode client;
LightClient client = new LightClient(args, rpcApp);

switch (nodeRole) {
case FULL -> {
client = new FullNode();
}
case LIGHT -> {
client = new LightClient();
}
case NONE -> {
// This shouldn't happen.
// TODO: don't use this enum for the CLI NodeRole option
return;
}
default -> {
log.log(Level.SEVERE, "Node role {0} not yet implemented.", nodeRole);
return;
}
}

// Start the client
// NOTE: This starts the beans the client would need - mutates the global context
client.start();
log.log(Level.INFO, "\uD83D\uDE80Started {0} client!", nodeRole);

Signal.handle(new Signal("INT"), signal -> {
rpcApp.stop(); // NOTE: rpcApp is responsible for stopping everything that could've been started

// TODO: Maybe think of another place to hold the logic below
log.log(Level.INFO, "\uD83D\uDED1Stopped {0} client!", nodeRole);
System.exit(0);
});
Signal.handle(new Signal("INT"), signal -> client.stop());
}
}
2 changes: 0 additions & 2 deletions src/main/java/com/limechain/cli/Cli.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ public CliArguments parseArgs(String[] args) {
String dbPath = cmd.getOptionValue(DB_PATH, DBInitializer.DEFAULT_DIRECTORY);
boolean dbRecreate = cmd.hasOption(DB_RECREATE);
String nodeKey = cmd.getOptionValue(NODE_KEY);
// TODO: separation of enums; this NodeRole enum is used for blockannounce
// what does running the node in NodeMode NONE mean?
String nodeMode = cmd.getOptionValue(NODE_MODE, NodeRole.FULL.toString());

return new CliArguments(network, dbPath, dbRecreate, nodeKey, nodeMode);
Expand Down
41 changes: 0 additions & 41 deletions src/main/java/com/limechain/client/FullNode.java

This file was deleted.

12 changes: 0 additions & 12 deletions src/main/java/com/limechain/client/HostNode.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.limechain.client;
package com.limechain.lightclient;

import com.limechain.network.ConnectionManager;
import com.limechain.network.Network;
import com.limechain.rpc.server.AppBean;
import com.limechain.rpc.server.RpcApp;
import com.limechain.sync.warpsync.WarpSyncMachine;
import lombok.SneakyThrows;
import lombok.extern.java.Log;
Expand All @@ -14,26 +15,28 @@
* the client and hold references to dependencies
*/
@Log
public class LightClient implements HostNode {
public class LightClient {
// TODO: Add service dependencies i.e rpc, sync, network, etc.
// TODO: Do we need those as fields here...?
private final String[] cliArgs;
private final RpcApp rpcApp;
private final ConnectionManager connectionManager = ConnectionManager.getInstance();
private final Network network;
private Network network;
private WarpSyncMachine warpSyncMachine;

/**
* @implNote the RpcApp is assumed to have been started before constructing the client,
* as it relies on the application context
*/
public LightClient() {
this.network = AppBean.getBean(Network.class);
public LightClient(String[] cliArgs, RpcApp rpcApp) {
this.cliArgs = cliArgs;
this.rpcApp = rpcApp;
}

/**
* Starts the light client by instantiating all dependencies and services
*/
@SneakyThrows
public void start() {
// TODO: Add business logic
this.rpcApp.start(cliArgs);

this.network = AppBean.getBean(Network.class);
this.network.start();

while (true) {
Expand All @@ -42,6 +45,7 @@ public void start() {
log.log(Level.INFO, "Node successfully connected to a peer! Sync can start!");
this.warpSyncMachine = AppBean.getBean(WarpSyncMachine.class);
this.warpSyncMachine.start();
log.log(Level.INFO, "\uD83D\uDE80Started light client!");
break;
} else {
this.network.updateCurrentSelectedPeer();
Expand All @@ -51,4 +55,20 @@ public void start() {
Thread.sleep(10000);
}
}

/**
* Stops the light client by shutting down all running services
*/
public void stop() {
// TODO: Stop running services
this.warpSyncMachine.stop();
this.network.stop();
this.rpcApp.stop();
log.log(Level.INFO, "\uD83D\uDED1Stopped light client!");
doExit();
}

protected void doExit() {
System.exit(0);
}
}
34 changes: 8 additions & 26 deletions src/main/java/com/limechain/rpc/server/RpcApp.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.limechain.rpc.server;

import com.limechain.config.SystemInfo;
import com.limechain.network.Network;
import com.limechain.sync.warpsync.WarpSyncMachine;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
Expand All @@ -15,10 +14,10 @@
*/
@SpringBootApplication
@ComponentScan(basePackages = {
"com.limechain.rpc.config",
"com.limechain.rpc.methods",
"com.limechain.rpc.server",
"com.limechain.storage"
"com.limechain.rpc.config",
"com.limechain.rpc.methods",
"com.limechain.rpc.server",
"com.limechain.storage"
})
public class RpcApp {

Expand All @@ -27,16 +26,6 @@ public class RpcApp {
*/
private final String serverPort = "9922";

/**
* The reference to the underlying SpringApplication
*/
private final SpringApplication app;

public RpcApp() {
this.app = new SpringApplication(RpcApp.class);
app.setDefaultProperties(Collections.singletonMap("server.port", serverPort));
}

/**
* Spring application context
*/
Expand All @@ -47,9 +36,11 @@ public RpcApp() {
*
* @param cliArgs arguments that will be passed as
* ApplicationArguments to {@link com.limechain.rpc.config.CommonConfig}.
* @see com.limechain.rpc.config.CommonConfig#hostConfig(com.limechain.cli.CliArguments)
* @see com.limechain.rpc.config.CommonConfig#hostConfig(ApplicationArguments)
*/
public void start(String[] cliArgs) {
SpringApplication app = new SpringApplication(RpcApp.class);
app.setDefaultProperties(Collections.singletonMap("server.port", serverPort));
ConfigurableApplicationContext ctx = app.run(cliArgs);
ctx.getBean(SystemInfo.class).logSystemInfo();
this.springCtx = ctx;
Expand All @@ -59,15 +50,6 @@ public void start(String[] cliArgs) {
* Shuts down the spring application as well as any services that it's using
*/
public void stop() {
// TODO: This is untestable with our current design... but do we need to test it really?
// (I mean verifying that everything necessary has been stopped)

// TODO: Think of a way to make those beans lifecycle-aware so that stopping the context would propagate
// to stopping the necessary instances
// Perhaps Spring can handle this for us instead of us manually stopping the beans?
AppBean.getBean(WarpSyncMachine.class).stop();
AppBean.getBean(Network.class).stop();

if (this.springCtx != null) {
this.springCtx.stop();
}
Expand Down
54 changes: 54 additions & 0 deletions src/test/java/com/limechain/lightclient/LightClientTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.limechain.lightclient;

import com.limechain.network.Network;
import com.limechain.rpc.server.RpcApp;
import com.limechain.sync.warpsync.WarpSyncMachine;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;

import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

class LightClientTest {
private LightClient lightClient;

private RpcApp rpcApp;
private String[] args;

// Setting private fields. Not a good idea in general
private void setPrivateField(String fieldName, Object value)
throws NoSuchFieldException, IllegalAccessException {
Field privateField = LightClient.class.getDeclaredField(fieldName);
privateField.setAccessible(true);

privateField.set(lightClient, value);
}

@BeforeEach
public void setup() {
rpcApp = mock(RpcApp.class);
args = new String[]{"some args"};

lightClient = spy(new LightClient(args, rpcApp));
}

@Test
void lightClient_stop_invokesStopFunctions() throws NoSuchFieldException, IllegalAccessException {
Network network = mock(Network.class);
WarpSyncMachine warpSync = mock(WarpSyncMachine.class);

setPrivateField("network", network);
setPrivateField("warpSyncMachine", warpSync);
doNothing().when(lightClient).doExit();

lightClient.stop();

verify(network, times(1)).stop();
verify(rpcApp, times(1)).stop();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ public void stopNode() {
}

@Test
@Disabled("No response is received")
//TODO: See https://github.com/orgs/LimeChain/projects/16?pane=issue&itemId=40022251
@Disabled("Integration test")
void remoteBlockRequest_returnCorrectBlock_ifGivenBlockHash() {
var peerId = PeerId.fromBase58(PEER_ID);
//CHECKSTYLE.OFF
Expand All @@ -78,8 +77,7 @@ void remoteBlockRequest_returnCorrectBlock_ifGivenBlockHash() {
}

@Test
@Disabled("No response is received")
//TODO: See https://github.com/orgs/LimeChain/projects/16?pane=issue&itemId=40022251
@Disabled("Integration test")
void remoteBlockRequest_returnCorrectBlock_ifGivenBlockNumber() {
var peerId = PeerId.fromBase58(PEER_ID);
//CHECKSTYLE.OFF
Expand All @@ -101,7 +99,7 @@ void remoteBlockRequest_returnCorrectBlock_ifGivenBlockNumber() {

@Test
@Disabled("No response is received")
//TODO: See https://github.com/orgs/LimeChain/projects/16?pane=issue&itemId=40022251
//TODO: See https://github.com/orgs/LimeChain/projects/16?pane=issue&itemId=40022251
void remoteFunctions_return_correctData() {
var peerId = PeerId.fromBase58(PEER_ID);
var receivers = new String[]{"/dns/p2p.4.polkadot.network/tcp/30333/p2p/" + PEER_ID};
Expand Down

0 comments on commit 1a15dd3

Please sign in to comment.