URI: 
       tnetwork.best_effort_reliable: force DC if req times out; retry on new iface - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 3e2c5e8656dbbaa46405bec94bf4e58e83d4a113
   DIR parent 4984890265f0f8a83c8bca23be318a02abb7f8b2
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Thu, 27 Sep 2018 21:15:07 +0200
       
       network.best_effort_reliable: force DC if req times out; retry on new iface
       
       Diffstat:
         M electrum/interface.py               |       1 -
         M electrum/network.py                 |      27 +++++++++++++++++++--------
       
       2 files changed, 19 insertions(+), 9 deletions(-)
       ---
   DIR diff --git a/electrum/interface.py b/electrum/interface.py
       t@@ -130,7 +130,6 @@ def serialize_server(host: str, port: Union[str, int], protocol: str) -> str:
        class Interface(PrintError):
        
            def __init__(self, network, server, config_path, proxy):
       -        self.exception = None
                self.ready = asyncio.Future()
                self.got_disconnected = asyncio.Future()
                self.server = server
   DIR diff --git a/electrum/network.py b/electrum/network.py
       t@@ -642,17 +642,28 @@ class Network(PrintError):
                async def make_reliable_wrapper(self, *args, **kwargs):
                    for i in range(10):
                        iface = self.interface
       -                session = iface.session if iface else None
       -                if not session:
       -                    # no main interface; try again
       +                # retry until there is a main interface
       +                if not iface:
                            await asyncio.sleep(0.1)
       -                    continue
       +                    continue  # try again
       +                # wait for it to be usable
       +                iface_ready = iface.ready
       +                iface_disconnected = iface.got_disconnected
       +                await asyncio.wait([iface_ready, iface_disconnected], return_when=asyncio.FIRST_COMPLETED)
       +                if not iface_ready.done() or iface_ready.cancelled():
       +                    await asyncio.sleep(0.1)
       +                    continue  # try again
       +                # try actual request
                        success_fut = asyncio.ensure_future(func(self, *args, **kwargs))
       -                disconnected_fut = asyncio.shield(iface.got_disconnected)
       -                await asyncio.wait([success_fut, disconnected_fut], return_when=asyncio.FIRST_COMPLETED)
       -                if success_fut.done():
       +                await asyncio.wait([success_fut, iface_disconnected], return_when=asyncio.FIRST_COMPLETED)
       +                if success_fut.done() and not success_fut.cancelled():
                            if success_fut.exception():
       -                        raise success_fut.exception()
       +                        try:
       +                            raise success_fut.exception()
       +                        except RequestTimedOut:
       +                            await iface.close()
       +                            await iface_disconnected
       +                            continue  # try again
                            return success_fut.result()
                        # otherwise; try again
                    raise Exception('no interface to do request on... gave up.')