diff options
author | Lars-Dominik Braun <lars@6xq.net> | 2019-06-18 13:41:53 +0200 |
---|---|---|
committer | Lars-Dominik Braun <lars@6xq.net> | 2019-06-18 13:41:53 +0200 |
commit | b4669705fa8e581c17bbe0ca0c7cf4fadbd3deb8 (patch) | |
tree | b64aa972023caed27ab5158e4e49aecb008a4bdf /crocoite/browser.py | |
parent | c33431e6c5ccf5c0b274e2ed9c21ddf776759b67 (diff) | |
download | crocoite-b4669705fa8e581c17bbe0ca0c7cf4fadbd3deb8.tar.gz crocoite-b4669705fa8e581c17bbe0ca0c7cf4fadbd3deb8.tar.bz2 crocoite-b4669705fa8e581c17bbe0ca0c7cf4fadbd3deb8.zip |
Fix idle state tracking race condition
Closes #16. Expose SiteLoader’s page idle changes through events and
move state tracking into controller event handler. Relies on tracking
time instead of asyncio event, which is more reliable.
Diffstat (limited to 'crocoite/browser.py')
-rw-r--r-- | crocoite/browser.py | 49 |
1 files changed, 18 insertions, 31 deletions
diff --git a/crocoite/browser.py b/crocoite/browser.py index 10eaaff..577e77a 100644 --- a/crocoite/browser.py +++ b/crocoite/browser.py @@ -246,31 +246,17 @@ class RequestResponsePair: except TabException: self.response.body = None -class VarChangeEvent: - """ Notify when variable is changed """ - - __slots__ = ('_value', 'event') - - def __init__ (self, value): - self._value = value - self.event = asyncio.Event() +class NavigateError (IOError): + pass - def set (self, value): - if value != self._value: - self._value = value - # unblock waiting threads - self.event.set () - self.event.clear () +class PageIdle: + """ Page idle event """ - def get (self): - return self._value + def __init__ (self, idle): + self.idle = idle - async def wait (self): - await self.event.wait () - return self._value - -class NavigateError (IOError): - pass + def __bool__ (self): + return self.idle class SiteLoader: """ @@ -280,7 +266,7 @@ class SiteLoader: """ __slots__ = ('requests', 'browser', 'logger', 'tab', '_iterRunning', - 'idle', '_framesLoading') + '_framesLoading') allowedSchemes = {'http', 'https'} def __init__ (self, browser, logger): @@ -289,7 +275,6 @@ class SiteLoader: self.logger = logger.bind (context=type (self).__name__) self._iterRunning = [] - self.idle = VarChangeEvent (True) self._framesLoading = set () async def __aenter__ (self): @@ -343,22 +328,24 @@ class SiteLoader: # we need to block (yield) for every item completed, but not # handled by the consumer (caller). running = self._iterRunning - running.append (asyncio.ensure_future (self.tab.get ())) + tabGetTask = asyncio.ensure_future (self.tab.get ()) + running.append (tabGetTask) while True: done, pending = await asyncio.wait (running, return_when=asyncio.FIRST_COMPLETED) for t in done: result = t.result () if result is None: pass - elif isinstance (result, RequestResponsePair): - yield result - else: + elif t == tabGetTask: method, data = result f = handler.get (method, None) if f is not None: task = asyncio.ensure_future (f (**data)) pending.add (task) - pending.add (asyncio.ensure_future (self.tab.get ())) + tabGetTask = asyncio.ensure_future (self.tab.get ()) + pending.add (tabGetTask) + else: + yield result running = pending self._iterRunning = running @@ -492,7 +479,7 @@ class SiteLoader: uuid='bbeb39c0-3304-4221-918e-f26bd443c566', args=kwargs) self._framesLoading.add (kwargs['frameId']) - self.idle.set (False) + return PageIdle (False) async def _frameStoppedLoading (self, **kwargs): self.logger.debug ('frameStoppedLoading', @@ -500,5 +487,5 @@ class SiteLoader: self._framesLoading.remove (kwargs['frameId']) if not self._framesLoading: - self.idle.set (True) + return PageIdle (True) |