diff --git a/src/sakia/data/connectors/bma.py b/src/sakia/data/connectors/bma.py index 071bd1b017d046f352908d016fd14de01c9fbf76..456f7d8225dc80f80a6abd5a0d2162d72eeeb862 100644 --- a/src/sakia/data/connectors/bma.py +++ b/src/sakia/data/connectors/bma.py @@ -182,6 +182,8 @@ class BmaConnector: async def verified_get(self, currency, request, req_args): # If no node is known as a member, lookup synced nodes as a fallback synced_nodes = self._nodes_processor.synced_nodes(currency) + offline_nodes = self._nodes_processor.offline_synced_nodes(currency) + random_offline_node = random.sample(offline_nodes, min(1, len(offline_nodes))) nodes_generator = (n for n in synced_nodes) answers = {} answers_data = {} @@ -205,6 +207,10 @@ class BmaConnector: futures.append(self._verified_request(node, request(next( endpoint.conn_handler(session, proxy=self._user_parameters.proxy())), **req_args))) + if random_offline_node: + futures.append(self._verified_request(random_offline_node[0], request(next( + endpoint.conn_handler(session, proxy=self._user_parameters.proxy())), + **req_args))) except StopIteration: # When no more node is available, we go out of the while loop break diff --git a/src/sakia/data/processors/nodes.py b/src/sakia/data/processors/nodes.py index 1e334fc46d8a88133913031ad9a52150b094b84f..feb2db0bf4506983179a1758de51173579c282cf 100644 --- a/src/sakia/data/processors/nodes.py +++ b/src/sakia/data/processors/nodes.py @@ -40,6 +40,13 @@ class NodesProcessor: current_buid = self._repo.current_buid(currency=currency) return self._repo.get_synced_nodes(currency, current_buid) + def offline_synced_nodes(self, currency): + """ + Get nodes which are in the ONLINE state. + """ + current_buid = self._repo.current_buid(currency=currency) + return self._repo.get_offline_synced_nodes(currency, current_buid) + def synced_members_nodes(self, currency): """ Get nodes which are in the ONLINE state. @@ -168,13 +175,13 @@ class NodesProcessor: def handle_success(self, node): if not node.online(): node.last_state_change = time.time() - node.state = node.state - 1 + node.state = max(0, node.state - 1) self.update_node(node) def handle_failure(self, node, weight=1): if node.state + weight > Node.FAILURE_THRESHOLD and node.online(): node.last_state_change = time.time() - node.state += weight + node.state = min(5, node.state + weight) self.update_node(node) def drop_all(self, currency): diff --git a/src/sakia/data/repositories/nodes.py b/src/sakia/data/repositories/nodes.py index c670a81d91951b1954b79facd29fb8bab343806d..d09ff70473178ac1466771f638ed263d96056746 100644 --- a/src/sakia/data/repositories/nodes.py +++ b/src/sakia/data/repositories/nodes.py @@ -150,6 +150,17 @@ class NodesRepo: return [Node(*data) for data in datas] return [] + def get_offline_synced_nodes(self, currency, current_buid): + c = self._conn.execute("SELECT * FROM nodes " + "WHERE currency == ? " + "AND state > ?" + "AND current_buid == ?", + (currency, Node.FAILURE_THRESHOLD, current_buid)) + datas = c.fetchall() + if datas: + return [Node(*data) for data in datas] + return [] + def current_buid(self, currency): c = self._conn.execute("""SELECT COUNT(`uid`) FROM `nodes` diff --git a/src/sakia/services/network.py b/src/sakia/services/network.py index f4e10d750cfb47a7a3019fbe14a599351c839768..60d8ded2b0ac741906d226242b4c838973d9468c 100644 --- a/src/sakia/services/network.py +++ b/src/sakia/services/network.py @@ -209,13 +209,13 @@ class NetworkService(QObject): except InvalidNodeCurrency as e: self._logger.debug(str(e)) if self._blockchain_service.initialized(): + self._processor.handle_success(node) try: identity = await self._identities_service.find_from_pubkey(node.pubkey) identity = await self._identities_service.load_requirements(identity) node.member = identity.member node.uid = identity.uid self._processor.update_node(node) - self._processor.handle_success(node) self.node_changed.emit(node) except errors.DuniterError as e: self._logger.error(e.message)