Skip to content
Snippets Groups Projects
Commit 3490e96f authored by vjrj's avatar vjrj
Browse files

Take into account node current blocks

parent 5f00ed70
No related branches found
No related tags found
No related merge requests found
...@@ -8,33 +8,31 @@ part 'node.g.dart'; ...@@ -8,33 +8,31 @@ part 'node.g.dart';
@JsonSerializable() @JsonSerializable()
class Node extends Equatable implements IsJsonSerializable<Node> { class Node extends Equatable implements IsJsonSerializable<Node> {
const Node({ const Node(
required this.url, {required this.url,
this.latency = 99999, this.latency = 99999,
this.errors = 0, this.errors = 0,
}); this.currentBlock = 0});
factory Node.fromJson(Map<String, dynamic> json) => _$NodeFromJson(json); factory Node.fromJson(Map<String, dynamic> json) => _$NodeFromJson(json);
final String url; final String url;
final int latency; final int latency;
final int errors; final int errors;
final int currentBlock;
Node copyWith({ Node copyWith({String? url, int? latency, int? errors, int? currentBlock}) {
String? url,
int? latency,
int? errors,
}) {
return Node( return Node(
url: url ?? this.url, url: url ?? this.url,
latency: latency ?? this.latency, latency: latency ?? this.latency,
errors: errors ?? this.errors, errors: errors ?? this.errors,
currentBlock: currentBlock ?? this.currentBlock,
); );
} }
@override @override
String toString() { String toString() {
return 'node url: $url latency: $latency errors: $errors'; return 'node url: $url latency: $latency errors: $errors currentBlock: $currentBlock';
} }
@override @override
...@@ -44,7 +42,7 @@ class Node extends Equatable implements IsJsonSerializable<Node> { ...@@ -44,7 +42,7 @@ class Node extends Equatable implements IsJsonSerializable<Node> {
Node fromJson(Map<String, dynamic> json) => Node.fromJson(json); Node fromJson(Map<String, dynamic> json) => Node.fromJson(json);
@override @override
List<Object?> get props => <dynamic>[url, latency, errors]; List<Object?> get props => <dynamic>[url, latency, errors, currentBlock];
} }
List<Node> readDotNodeConfig(String entry) => List<Node> readDotNodeConfig(String entry) =>
......
...@@ -253,11 +253,14 @@ Future<List<Node>> _fetchDuniterNodesFromPeers(NodeType type) async { ...@@ -253,11 +253,14 @@ Future<List<Node>> _fetchDuniterNodesFromPeers(NodeType type) async {
!endpoint.contains('test') && !endpoint.contains('test') &&
!endpoint.contains('localhost')) { !endpoint.contains('localhost')) {
try { try {
final Duration latency = await _pingNode(endpoint, type); final NodeCheck nodeCheck = await _pingNode(endpoint, type);
final Duration latency = nodeCheck.latency;
logger( logger(
'Evaluating node: $endpoint, latency ${latency.inMicroseconds}'); 'Evaluating node: $endpoint, latency ${latency.inMicroseconds} currentBlock: ${nodeCheck.currentBlock}');
final Node node = final Node node = Node(
Node(url: endpoint, latency: latency.inMicroseconds); url: endpoint,
latency: latency.inMicroseconds,
currentBlock: nodeCheck.currentBlock);
if (fastestNode == null || latency < fastestLatency) { if (fastestNode == null || latency < fastestLatency) {
fastestNode = endpoint; fastestNode = endpoint;
fastestLatency = latency; fastestLatency = latency;
...@@ -308,9 +311,13 @@ Future<List<Node>> _fetchNodes(NodeType type) async { ...@@ -308,9 +311,13 @@ Future<List<Node>> _fetchNodes(NodeType type) async {
final String endpoint = node.url; final String endpoint = node.url;
try { try {
final Duration latency = await _pingNode(endpoint, type); final NodeCheck nodeCheck = await _pingNode(endpoint, type);
final Duration latency = nodeCheck.latency;
logger('Evaluating node: $endpoint, latency ${latency.inMicroseconds}'); logger('Evaluating node: $endpoint, latency ${latency.inMicroseconds}');
final Node node = Node(url: endpoint, latency: latency.inMicroseconds); final Node node = Node(
url: endpoint,
latency: latency.inMicroseconds,
currentBlock: nodeCheck.currentBlock);
if (fastestNode == null || latency < fastestLatency) { if (fastestNode == null || latency < fastestLatency) {
fastestNode = endpoint; fastestNode = endpoint;
fastestLatency = latency; fastestLatency = latency;
...@@ -341,8 +348,9 @@ Future<List<Node>> _fetchNodes(NodeType type) async { ...@@ -341,8 +348,9 @@ Future<List<Node>> _fetchNodes(NodeType type) async {
return lNodes; return lNodes;
} }
Future<Duration> _pingNode(String node, NodeType type) async { Future<NodeCheck> _pingNode(String node, NodeType type) async {
const Duration timeout = Duration(seconds: 10); const Duration timeout = Duration(seconds: 10);
int currentBlock = 0;
try { try {
final Stopwatch stopwatch = Stopwatch()..start(); final Stopwatch stopwatch = Stopwatch()..start();
if (type == NodeType.duniter || type == NodeType.cesiumPlus) { if (type == NodeType.duniter || type == NodeType.cesiumPlus) {
...@@ -360,16 +368,15 @@ Future<Duration> _pingNode(String node, NodeType type) async { ...@@ -360,16 +368,15 @@ Future<Duration> _pingNode(String node, NodeType type) async {
} else { } else {
// Test GVA with a query // Test GVA with a query
final Gva gva = Gva(node: proxyfyNode(node)); final Gva gva = Gva(node: proxyfyNode(node));
await gva currentBlock = await gva.getCurrentBlock().timeout(timeout);
.balance('EdWkzNABz7dPancFqW6JVLqv1wpGaQSxgWmMf1pmY7KG') // NodeManager().updateNode(type, node.copyWith(latency: newLatency));
.timeout(timeout);
} }
stopwatch.stop(); stopwatch.stop();
return stopwatch.elapsed; return NodeCheck(latency: stopwatch.elapsed, currentBlock: currentBlock);
} catch (e) { } catch (e) {
// Handle exception when node is unavailable etc // Handle exception when node is unavailable etc
logger('Node $node does not respond to ping $e'); logger('Node $node does not respond to ping $e');
return const Duration(days: 2); return NodeCheck(latency: const Duration(days: 2), currentBlock: 0);
} }
} }
...@@ -528,10 +535,17 @@ Future<String?> gvaNick(String pubKey) async { ...@@ -528,10 +535,17 @@ Future<String?> gvaNick(String pubKey) async {
Future<T?> gvaFunctionWrapper<T>( Future<T?> gvaFunctionWrapper<T>(
String pubKey, Future<T?> Function(Gva) specificFunction) async { String pubKey, Future<T?> Function(Gva) specificFunction) async {
final List<Node> nodes = NodeManager() final List<Node> fnodes = NodeManager()
.nodeList(NodeType.gva) .nodeList(NodeType.gva)
.where((Node node) => node.errors <= NodeManager.maxNodeErrors) .where((Node node) => node.errors <= NodeManager.maxNodeErrors)
.toList(); .toList();
final int maxCurrentBlock = fnodes.fold(
0,
(int max, Node node) =>
node.currentBlock > max ? node.currentBlock : max);
final List<Node> nodes = fnodes
.where((Node node) => node.currentBlock == maxCurrentBlock)
.toList();
if (nodes.isEmpty) { if (nodes.isEmpty) {
nodes.addAll(defaultGvaNodes); nodes.addAll(defaultGvaNodes);
} }
...@@ -556,6 +570,12 @@ Future<T?> gvaFunctionWrapper<T>( ...@@ -556,6 +570,12 @@ Future<T?> gvaFunctionWrapper<T>(
continue; continue;
} }
} }
throw Exception( throw Exception('Sorry: I cannot find a working gva node');
'Sorry: I cannot find a working node to get your transactions'); }
class NodeCheck {
NodeCheck({required this.latency, required this.currentBlock});
final Duration latency;
final int currentBlock;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment