# HG changeset patch # User Goffi # Date 1688638225 -7200 # Node ID be20e6ac9f22674ea28e82528606ee2072e2c734 # Parent 9b451115e726131ca7167d2d2f7a4e7a310917e8 browser (bridge): add methods/properties to wait for Websocket/BroadcastChannel to be ready diff -r 9b451115e726 -r be20e6ac9f22 libervia/web/pages/_browser/bridge.py --- a/libervia/web/pages/_browser/bridge.py Thu Jul 06 12:07:29 2023 +0200 +++ b/libervia/web/pages/_browser/bridge.py Thu Jul 06 12:10:25 2023 +0200 @@ -39,14 +39,25 @@ def __init__(self, broadcast_channel): self.broadcast_channel = broadcast_channel self.token = window.ws_token + self.socket = None self.create_socket() self.retrying = False self.network_error = False + self._ready_fut = aio.Future() @property def profile(self): return self.broadcast_channel.profile + @property + def is_ready(self): + return False if self.socket is None else self.socket.readyState == "OPEN" + + @property + def connection_ready_fut(self): + """Future resolved when connection is ready""" + return self._ready_fut + def retry_connect(self) -> None: if self.retrying: return @@ -100,6 +111,7 @@ def on_open(self, evt) -> None: log.info("websocket connection opened") + self._ready_fut.set_result(None) self.send("init", {"profile": self.profile, "token": self.token}) def on_error(self, evt) -> None: @@ -151,6 +163,8 @@ def __init__(self): log.debug(f"BroadcastChannel init with profile {self.profile!r}") + self.ws = None + self._connected = False self.start = time.time() self.bc = window.BroadcastChannel.new("libervia") self.bc.bind("message", self.on_message) @@ -158,7 +172,6 @@ # API, thus we wait a bit to see if somebody is answering. If not, we are probably # the first tab. self.check_connection_timer = timer.set_timeout(self.establish_connection, 20) - self.ws = None # set of all known tab ids self.tabs_ids = {tab_id} self.post("salut_a_vous", { @@ -166,6 +179,7 @@ "profile": self.profile }) window.bind("unload", self.on_unload) + self._wait_connection_fut = aio.Future() @property def profile(self): @@ -176,6 +190,12 @@ """True is this tab is the one establishing the websocket connection""" return self.ws is not None + async def _wait_for_ws(self): + assert self.ws is not None + await self.ws.connection_ready_fut + self._wait_connection_fut.set_result(None) + self._connected = True + @connecting_tab.setter def connecting_tab(self, connecting: bool) -> None: if connecting: @@ -184,9 +204,20 @@ self.post("connection", { "tab_id": tab_id }) + aio.run(self._wait_for_ws()) + elif self.ws is not None: self.ws.close() + @property + def connected(self): + return self._connected + + async def wait_for_connection(self): + if self._connected: + return + await self._wait_connection_fut + def establish_connection(self) -> None: """Called when there is no existing connection""" timer.clear_timeout(self.check_connection_timer) @@ -219,6 +250,8 @@ log.info(f"there is already a connection to server at tab {other_tab_id}") timer.clear_timeout(self.check_connection_timer) self.check_connection_timer = None + self._wait_connection_fut.set_result(None) + self._connected = True elif data["type"] == "salut_a_vous": # a new tab has just been created if data["profile"] != self.profile: