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