Moving away of NetworkService and graphenej in general the decision to close connection to the current node and retry with another one just because the node does not provide the info needed in PalmPay. Graphenej has to be as app agnostic as possible so a new public method 'removeCurrentNodeAndReconnect()' was implemeted to do the removal and reconnection, and the app that uses graphenej has to decide by its own metrics to remove the current connected node and call such public method.

This commit is contained in:
Severiano Jaramillo 2018-11-07 21:20:36 -06:00
parent 214891fcc9
commit dee17a12be

View file

@ -80,7 +80,7 @@ public class NetworkService extends Service {
private final String TAG = this.getClass().getName(); private final String TAG = this.getClass().getName();
public static final int NORMAL_CLOSURE_STATUS = 1000; public static final int NORMAL_CLOSURE_STATUS = 1000;
private static final int NO_HISTORY_CLOSURE_STATUS = 1001; private static final int GOING_AWAY_STATUS = 1001;
// Time to wait before retrying a connection attempt // Time to wait before retrying a connection attempt
private static final int DEFAULT_RETRY_DELAY = 500; private static final int DEFAULT_RETRY_DELAY = 500;
@ -341,6 +341,14 @@ public class NetworkService extends Service {
} }
} }
/**
* Public method that can be called from classes that bind to the service and find out that
* for any reason want the service to connect to a different node.
*/
public void removeCurrentNodeAndReconnect() {
mWebSocket.close(GOING_AWAY_STATUS, null);
}
/** /**
* Runnable that will perform a connection attempt with the best node after DEFAULT_INITIAL_DELAY * Runnable that will perform a connection attempt with the best node after DEFAULT_INITIAL_DELAY
* milliseconds. This is used only if the node latency verification is activated. * milliseconds. This is used only if the node latency verification is activated.
@ -566,9 +574,6 @@ public class NetworkService extends Service {
} else if (requestClass == GetFullAccounts.class) { } else if (requestClass == GetFullAccounts.class) {
Type GetFullAccountsResponse = new TypeToken<JsonRpcResponse<List<FullAccountDetails>>>(){}.getType(); Type GetFullAccountsResponse = new TypeToken<JsonRpcResponse<List<FullAccountDetails>>>(){}.getType();
parsedResponse = gson.fromJson(text, GetFullAccountsResponse); parsedResponse = gson.fromJson(text, GetFullAccountsResponse);
if(parsedResponse != null)
verifyNodeHasHistoryApi(parsedResponse);
} else if(requestClass == GetKeyReferences.class){ } else if(requestClass == GetKeyReferences.class){
Type GetKeyReferencesResponse = new TypeToken<JsonRpcResponse<List<List<UserAccount>>>>(){}.getType(); Type GetKeyReferencesResponse = new TypeToken<JsonRpcResponse<List<List<UserAccount>>>>(){}.getType();
parsedResponse = gson.fromJson(text, GetKeyReferencesResponse); parsedResponse = gson.fromJson(text, GetKeyReferencesResponse);
@ -591,30 +596,6 @@ public class NetworkService extends Service {
RxBus.getBusInstance().send(parsedResponse); RxBus.getBusInstance().send(parsedResponse);
} }
/**
* This method inspects the node response to find out if the totalOps is equal to zero,
* in that case the current connected node may not have the history plugin so we would need
* to close the connection and choose a different node.
*
* @param parsedResponse A JSONRpcResponse from a GetFullAccounts API call
*/
private void verifyNodeHasHistoryApi(JsonRpcResponse parsedResponse) {
if(parsedResponse.result instanceof List &&
((List) parsedResponse.result).size() > 0 &&
((List) parsedResponse.result).get(0) instanceof FullAccountDetails) {
FullAccountDetails fullAccountDetails = (FullAccountDetails) ((List) parsedResponse.result).get(0);
long totalOps = fullAccountDetails.getStatistics().total_ops;
if (totalOps == 0) {
Log.d(TAG, "The node returned 0 total_ops for current account and may not have installed the history plugin. " +
"Trying to connect to a different node.");
mWebSocket.close(NO_HISTORY_CLOSURE_STATUS, null);
}
}
}
/** /**
* Private method that will just broadcast a de-serialized notification to all interested parties * Private method that will just broadcast a de-serialized notification to all interested parties
* @param notification De-serialized notification * @param notification De-serialized notification
@ -674,10 +655,10 @@ public class NetworkService extends Service {
super.onClosed(webSocket, code, reason); super.onClosed(webSocket, code, reason);
Log.d(TAG,"onClosed"); Log.d(TAG,"onClosed");
if (code == NO_HISTORY_CLOSURE_STATUS) if (code == GOING_AWAY_STATUS)
handleWebSocketDisconnection(true); handleWebSocketDisconnection(true, true);
else else
handleWebSocketDisconnection(false); handleWebSocketDisconnection(false, false);
} }
@Override @Override
@ -694,16 +675,17 @@ public class NetworkService extends Service {
Log.e(TAG,"Response: "+response.message()); Log.e(TAG,"Response: "+response.message());
} }
handleWebSocketDisconnection(true); handleWebSocketDisconnection(true, false);
} }
/** /**
* Method that encapsulates the behavior of handling a disconnection to the current node, and * Method that encapsulates the behavior of handling a disconnection to the current node, and
* potentially tries to reconnect to another one. * potentially tries to reconnect to another one.
* *
* @param tryReconnection Variable that states if a reconnection to other node should be tried. * @param tryReconnection States if a reconnection to other node should be tried.
* @param removeSelectedNode States if the current node should be removed from the nodes list.
*/ */
private void handleWebSocketDisconnection(boolean tryReconnection) { private void handleWebSocketDisconnection(boolean tryReconnection, boolean removeSelectedNode) {
RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.DISCONNECTED, ApiAccess.API_NONE)); RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.DISCONNECTED, ApiAccess.API_NONE));
isLoggedIn = false; isLoggedIn = false;
@ -720,10 +702,16 @@ public class NetworkService extends Service {
mCurrentId = 0; mCurrentId = 0;
mApiIds.clear(); mApiIds.clear();
// Adding a very high latency value to this node in order to prevent if (removeSelectedNode) {
// us from getting it again // TODO change method to actually remove the node from the list
mSelectedNode.addLatencyValue(Long.MAX_VALUE); mSelectedNode.addLatencyValue(Long.MAX_VALUE);
nodeProvider.updateNode(mSelectedNode); nodeProvider.updateNode(mSelectedNode);
} else {
// Adding a very high latency value to this node in order to prevent
// us from getting it again
mSelectedNode.addLatencyValue(Long.MAX_VALUE);
nodeProvider.updateNode(mSelectedNode);
}
RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.DISCONNECTED, ApiAccess.API_NONE)); RxBus.getBusInstance().send(new ConnectionStatusUpdate(ConnectionStatusUpdate.DISCONNECTED, ApiAccess.API_NONE));