From 705c900049a96717b2cbc42f08d938e054c97c35 Mon Sep 17 00:00:00 2001
From: Inso <insomniak.fr@gmail.com>
Date: Fri, 26 Jun 2015 07:44:50 +0200
Subject: [PATCH] Stopping coroutines cleanly

---
 src/cutecoin/core/account.py     |  7 +++++++
 src/cutecoin/core/app.py         |  6 ++----
 src/cutecoin/core/community.py   | 25 ++-----------------------
 src/cutecoin/core/net/network.py |  4 ++--
 src/cutecoin/core/txhistory.py   | 23 ++++++++++++++++++-----
 src/cutecoin/core/wallet.py      |  4 ++++
 6 files changed, 35 insertions(+), 34 deletions(-)

diff --git a/src/cutecoin/core/account.py b/src/cutecoin/core/account.py
index 0bfbed84..c14a4275 100644
--- a/src/cutecoin/core/account.py
+++ b/src/cutecoin/core/account.py
@@ -592,6 +592,13 @@ class Account(QObject):
                     return
             self.broadcast_error.emit(r.error(), strdata)
 
+    def stop_coroutines(self):
+        for c in self.communities:
+            c.stop_coroutines()
+
+        for w in self.wallets:
+            w.stop_coroutines()
+
     def jsonify(self):
         '''
         Get the account in a json format.
diff --git a/src/cutecoin/core/app.py b/src/cutecoin/core/app.py
index 379b39cb..ef07dc2e 100644
--- a/src/cutecoin/core/app.py
+++ b/src/cutecoin/core/app.py
@@ -127,8 +127,7 @@ class Application(QObject):
         '''
         if self.current_account is not None:
             self.save_cache(self.current_account)
-            for c in self.current_account.communities:
-                c.network.stop_crawling()
+            self.current_account.stop_coroutines()
 
         self.current_account = account
 
@@ -399,8 +398,7 @@ class Application(QObject):
         return data
 
     def stop(self):
-        for c in self.current_account.communities:
-            c.network.stop_crawling()
+        self.current_account.stop_coroutines()
 
     def get_last_version(self):
         url = QUrl("https://api.github.com/repos/ucoin-io/cutecoin/releases")
diff --git a/src/cutecoin/core/community.py b/src/cutecoin/core/community.py
index 93c028de..7a612d09 100644
--- a/src/cutecoin/core/community.py
+++ b/src/cutecoin/core/community.py
@@ -264,29 +264,8 @@ class Community(QObject):
         memberships = self.bma_access.get(self, qtbma.wot.Members)
         return [m['pubkey'] for m in memberships["results"]]
 
-    def post(self, request, req_args={}, post_args={}):
-        '''
-        Post data to a community.
-        Only sends the data to one node.
-
-        :param request: A ucoinpy bma request class
-        :param req_args: Arguments to pass to the request constructor
-        :param post_args: Arguments to pass to the request __post__ method
-        :return: The returned data
-        '''
-        nodes = self._network.online_nodes
-        for node in nodes:
-            req = request(node.endpoint.conn_handler(), **req_args)
-            logging.debug("Trying to connect to : " + node.pubkey)
-            req = request(node.endpoint.conn_handler(), **req_args)
-            try:
-                req.post(**post_args)
-                return
-            except ValueError as e:
-                raise
-            except RequestException:
-                continue
-        raise NoPeerAvailable(self.currency, len(nodes))
+    def stop_coroutines(self):
+        self.network.stop_coroutines()
 
     def jsonify(self):
         '''
diff --git a/src/cutecoin/core/net/network.py b/src/cutecoin/core/net/network.py
index ddb73d6c..7646ff12 100644
--- a/src/cutecoin/core/net/network.py
+++ b/src/cutecoin/core/net/network.py
@@ -107,7 +107,7 @@ class Network(QObject):
         ratio_synced = synced / total
         return ratio_synced
 
-    def stop_crawling(self):
+    def stop_coroutines(self):
         '''
         Stop network nodes crawling.
         '''
@@ -202,9 +202,9 @@ class Network(QObject):
 
     @pyqtSlot(Peer)
     def handle_new_node(self, peer):
-        logging.debug("New node found : {0}".format(peer.pubkey[:5]))
         pubkeys = [n.pubkey for n in self.nodes]
         if peer.pubkey not in pubkeys:
+            logging.debug("New node found : {0}".format(peer.pubkey[:5]))
             node = Node.from_peer(self.network_manager, self.currency, peer)
             self.add_node(node)
             self.nodes_changed.emit()
diff --git a/src/cutecoin/core/txhistory.py b/src/cutecoin/core/txhistory.py
index b2690b93..d520d3ec 100644
--- a/src/cutecoin/core/txhistory.py
+++ b/src/cutecoin/core/txhistory.py
@@ -9,6 +9,7 @@ class TxHistory():
     def __init__(self, wallet):
         self._latest_block = 0
         self.wallet = wallet
+        self._stop_coroutines = False
 
         self._transfers = []
         self.available_sources = []
@@ -54,8 +55,11 @@ class TxHistory():
     def transfers(self):
         return [t for t in self._transfers if t.state != Transfer.DROPPED]
 
+    def stop_coroutines(self):
+        self._stop_coroutines = True
+
     @asyncio.coroutine
-    def _parse_transaction(self, community, txdata, received_list, txid):
+    def _parse_transaction(self, community, txdata, new_transfers, received_list, txid):
         if len(txdata['issuers']) == 0:
             True
 
@@ -111,7 +115,7 @@ class TxHistory():
             if txdata['hash'] not in [t['hash'] for t in awaiting]:
                 transfer = Transfer.create_validated(txdata['hash'],
                                                      metadata.copy())
-                self._transfers.append(transfer)
+                new_transfers.append(transfer)
         # If we are not in the issuers,
         # maybe it we are in the recipients of this transaction
         elif in_outputs:
@@ -123,7 +127,7 @@ class TxHistory():
             metadata['amount'] = amount
             received = Received(txdata['hash'], metadata.copy())
             received_list.append(received)
-            self._transfers.append(received)
+            new_transfers.append(received)
         return True
 
     @asyncio.coroutine
@@ -138,7 +142,7 @@ class TxHistory():
         block_data = yield from community.blockid()
         current_block = block_data['number']
         logging.debug("Refresh from : {0} to {1}".format(self.latest_block, current_block))
-
+        new_transfers = []
         # Lets look if transactions took too long to be validated
         awaiting = [t for t in self._transfers
                     if t.state == Transfer.AWAITING]
@@ -147,24 +151,33 @@ class TxHistory():
                                                       req_args={'pubkey': self.wallet.pubkey,
                                                              'from_':str(parsed_block),
                                                              'to_': str(parsed_block + 100)})
+            if self._stop_coroutines:
+                return
 
             # We parse only blocks with transactions
             transactions = tx_history['history']['received'] + tx_history['history']['sent']
             for (txid, txdata) in enumerate(transactions):
+                if self._stop_coroutines:
+                    return
                 if len(txdata['issuers']) == 0:
                     logging.debug("Error with : {0}, from {1} to {2}".format(self.wallet.pubkey,
                                                                              parsed_block,
                                                                              current_block))
                 else:
-                    yield from self._parse_transaction(community, txdata, received_list, txid)
+                    yield from self._parse_transaction(community, txdata, new_transfers, received_list, txid)
+
             self.wallet.refresh_progressed.emit(parsed_block, current_block, self.wallet.pubkey)
             parsed_block += 101
 
         if current_block > self.latest_block:
             self.available_sources = yield from self.wallet.future_sources(community)
+            if self._stop_coroutines:
+                return
             self.latest_block = current_block
 
         for transfer in awaiting:
             transfer.check_refused(current_block)
 
+        self._transfers = self._transfers + new_transfers
+
         self.wallet.refresh_finished.emit(received_list)
diff --git a/src/cutecoin/core/wallet.py b/src/cutecoin/core/wallet.py
index 949b5f3c..0d76ee22 100644
--- a/src/cutecoin/core/wallet.py
+++ b/src/cutecoin/core/wallet.py
@@ -331,6 +331,10 @@ class Wallet(QObject):
         else:
             return []
 
+    def stop_coroutines(self):
+        for c in self.caches.values():
+            c.stop_coroutines()
+
     def jsonify(self):
         '''
         Get the wallet as json format.
-- 
GitLab