Introducing the NodeProvider interface and its implementation LatencyNodeProvider
This commit is contained in:
parent
8c89c93935
commit
25222e5ea9
3 changed files with 156 additions and 0 deletions
|
@ -0,0 +1,55 @@
|
||||||
|
package cy.agorise.graphenej.network;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
public class LatencyNodeProvider implements NodeProvider {
|
||||||
|
private PriorityQueue<FullNode> mFullNodeHeap;
|
||||||
|
|
||||||
|
public LatencyNodeProvider(){
|
||||||
|
mFullNodeHeap = new PriorityQueue<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FullNode getBestNode() {
|
||||||
|
return mFullNodeHeap.peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNode(FullNode fullNode) {
|
||||||
|
mFullNodeHeap.add(fullNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateNode(FullNode fullNode) {
|
||||||
|
if(mFullNodeHeap.remove(fullNode)){
|
||||||
|
return mFullNodeHeap.offer(fullNode);
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates an existing node with the new latency value.
|
||||||
|
*
|
||||||
|
* @param fullNode Existing full node instance
|
||||||
|
* @param latency New latency measurement
|
||||||
|
* @return True if the node priority was updated successfully
|
||||||
|
*/
|
||||||
|
public boolean updateNode(FullNode fullNode, int latency){
|
||||||
|
if(mFullNodeHeap.remove(fullNode)){
|
||||||
|
fullNode.addLatencyValue(latency);
|
||||||
|
return mFullNodeHeap.add(fullNode);
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FullNode> getSortedNodes() {
|
||||||
|
FullNode[] nodeArray = mFullNodeHeap.toArray(new FullNode[mFullNodeHeap.size()]);
|
||||||
|
Arrays.sort(nodeArray);
|
||||||
|
return Arrays.asList(nodeArray);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package cy.agorise.graphenej.network;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface used to describe the high level characteristics of a class that will
|
||||||
|
* hold and manage a list of {@link FullNode} instances.
|
||||||
|
*
|
||||||
|
* The idea is that the class implementing this interface should provide node instances
|
||||||
|
* and thus URLs for the {@link cy.agorise.graphenej.api.android.NetworkService} with
|
||||||
|
* different sorting heuristics.
|
||||||
|
*/
|
||||||
|
public interface NodeProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node with the best characteristics.
|
||||||
|
* @return A FullNode instance
|
||||||
|
*/
|
||||||
|
FullNode getBestNode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new node to the queue
|
||||||
|
* @param fullNode {@link FullNode} instance to add.
|
||||||
|
*/
|
||||||
|
void addNode(FullNode fullNode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the rating of a specific node that is already in the NodeProvider
|
||||||
|
* @param fullNode
|
||||||
|
*/
|
||||||
|
boolean updateNode(FullNode fullNode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an ordered list of {@link FullNode} instances.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<FullNode> getSortedNodes();
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package cy.agorise.graphenej.network;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class LatencyNodeProviderTest {
|
||||||
|
private FullNode nodeA, nodeB, nodeC;
|
||||||
|
private LatencyNodeProvider latencyNodeProvider;
|
||||||
|
|
||||||
|
private void setupTestNodes(){
|
||||||
|
// Creating 3 nodes with different latencies
|
||||||
|
nodeA = new FullNode("wss://nodeA");
|
||||||
|
nodeB = new FullNode("wss://nodeB");
|
||||||
|
nodeC = new FullNode("wss://nodeC");
|
||||||
|
|
||||||
|
// Adding latencies measurements
|
||||||
|
nodeA.addLatencyValue(100);
|
||||||
|
nodeB.addLatencyValue(50);
|
||||||
|
nodeC.addLatencyValue(20);
|
||||||
|
|
||||||
|
// Creating a node provider and adding the nodes created previously
|
||||||
|
latencyNodeProvider = new LatencyNodeProvider();
|
||||||
|
latencyNodeProvider.addNode(nodeC);
|
||||||
|
latencyNodeProvider.addNode(nodeA);
|
||||||
|
latencyNodeProvider.addNode(nodeB);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSorting(){
|
||||||
|
setupTestNodes();
|
||||||
|
|
||||||
|
// Confirming that the best node is nodeC
|
||||||
|
FullNode bestNode = latencyNodeProvider.getBestNode();
|
||||||
|
System.out.println("Best node latency: "+bestNode.getLatencyValue());
|
||||||
|
Assert.assertSame("Check that the best node is nodeC", nodeC, bestNode);
|
||||||
|
|
||||||
|
// Improving nodeA score by feeding it with new better latency measurements
|
||||||
|
latencyNodeProvider.updateNode(nodeA, 10);
|
||||||
|
latencyNodeProvider.updateNode(nodeA, 10);
|
||||||
|
latencyNodeProvider.updateNode(nodeA, 10);
|
||||||
|
latencyNodeProvider.updateNode(nodeA, 10);
|
||||||
|
|
||||||
|
// Updating the nodeA position in the provider
|
||||||
|
latencyNodeProvider.updateNode(nodeA);
|
||||||
|
bestNode = latencyNodeProvider.getBestNode();
|
||||||
|
System.out.println("Best node latency after update: "+bestNode.getLatencyValue());
|
||||||
|
Assert.assertSame("Check that the best node now is the nodeA", nodeA, bestNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSortedList(){
|
||||||
|
setupTestNodes();
|
||||||
|
|
||||||
|
// Confirming that the getSortedNodes gives us a sorted list of nodes in increasing latency order
|
||||||
|
List<FullNode> fullNodeList = latencyNodeProvider.getSortedNodes();
|
||||||
|
Assert.assertSame(nodeC, fullNodeList.get(0));
|
||||||
|
Assert.assertSame(nodeB, fullNodeList.get(1));
|
||||||
|
Assert.assertSame(nodeA, fullNodeList.get(2));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue