fix: Fix up merging request changes and make sure that there is no racing condition errors, and UI always gets correct information.

ref: N25B-256
This commit is contained in:
Björn Otgaar
2025-11-11 10:18:43 +01:00
parent 2d1a25e4ae
commit debc87c0bb
3 changed files with 67 additions and 75 deletions

View File

@@ -56,28 +56,29 @@ class RICommunicationAgent(BaseAgent):
"we probably dont have any receivers... but let's check!"
)
# Wait up to {seconds_to_wait_total/2} seconds for a reply:)
# Wait up to {seconds_to_wait_total/2} seconds for a reply
try:
message = await asyncio.wait_for(
self.agent._req_socket.recv_json(), timeout=seconds_to_wait_total / 2
)
# We didnt get a reply :(
# We didnt get a reply
except TimeoutError:
self.agent.logger.info(
f"No ping retrieved in {seconds_to_wait_total} seconds, "
"sending UI disconnection event and soft killing myself."
"sending UI disconnection event and attempting to restart."
)
# Make sure we dont retry receiving messages untill we're setup.
self.agent.connected = False
self.agent.remove_behaviour(self)
# Tell UI we're disconnected.
topic = b"ping"
data = json.dumps(False).encode()
if self.agent.pub_socket is None:
self.agent.logger.error(
"communication agent pub socket not correctly initialized."
"Communication agent pub socket not correctly initialized."
)
else:
try:
@@ -85,17 +86,20 @@ class RICommunicationAgent(BaseAgent):
self.agent.pub_socket.send_multipart([topic, data]), 5
)
except TimeoutError:
self.agent.logger.error(
self.agent.logger.warning(
"Initial connection ping for router timed"
" out in ri_communication_agent."
)
# Try to reboot.
self.agent.logger.debug("Restarting communication agent.")
await self.agent.setup()
self.agent.logger.debug(f'Received message "{message}" from RI.')
if "endpoint" not in message:
self.agent.logger.error("No received endpoint in message, excepted ping endpoint.")
self.agent.logger.warning(
"No received endpoint in message, expected ping endpoint."
)
return
# See what endpoint we received
@@ -107,7 +111,7 @@ class RICommunicationAgent(BaseAgent):
await self.agent.pub_socket.send_multipart([topic, data])
await asyncio.sleep(1)
case _:
self.agent.logger.info(
self.agent.logger.debug(
"Received message with topic different than ping, while ping expected."
)
@@ -143,16 +147,20 @@ class RICommunicationAgent(BaseAgent):
if self._req_socket is None:
continue
# Send our message and receive one back:)
# Send our message and receive one back
message = {"endpoint": "negotiate/ports", "data": {}}
await self._req_socket.send_json(message)
retry_frequency = 1.0
try:
received_message = await asyncio.wait_for(self._req_socket.recv_json(), timeout=1.0)
received_message = await asyncio.wait_for(
self._req_socket.recv_json(), timeout=retry_frequency
)
except TimeoutError:
self.logger.warning(
"No connection established in 20 seconds (attempt %d/%d)",
"No connection established in %d seconds (attempt %d/%d)",
retries * retry_frequency,
retries + 1,
max_retries,
)
@@ -160,21 +168,21 @@ class RICommunicationAgent(BaseAgent):
continue
except Exception as e:
self.logger.error("Unexpected error during negotiation: %s", e)
self.logger.warning("Unexpected error during negotiation: %s", e)
retries += 1
continue
# Validate endpoint
endpoint = received_message.get("endpoint")
if endpoint != "negotiate/ports":
# TODO: Should this send a message back?
self.logger.error(
self.logger.warning(
"Invalid endpoint '%s' received (attempt %d/%d)",
endpoint,
retries + 1,
max_retries,
)
retries += 1
await asyncio.sleep(1)
continue
# At this point, we have a valid response
@@ -194,7 +202,7 @@ class RICommunicationAgent(BaseAgent):
if addr != self._address:
if not bind:
self._req_socket.connect(addr)
else: # TODO: Should this ever be the case?
else:
self._req_socket.bind(addr)
case "actuation":
ri_commands_agent = RICommandAgent(
@@ -210,31 +218,32 @@ class RICommunicationAgent(BaseAgent):
self.logger.warning("Unhandled negotiation id: %s", id)
except Exception as e:
self.logger.error("Error unpacking negotiation data: %s", e)
self.logger.warning("Error unpacking negotiation data: %s", e)
retries += 1
await asyncio.sleep(1)
continue
# setup succeeded
break
else:
self.logger.error("Failed to set up RICommunicationAgent after %d retries", max_retries)
self.logger.error("Failed to set up %s after %d retries", self.name, max_retries)
return
# Set up ping behaviour
listen_behaviour = self.ListenBehaviour()
self.add_behaviour(listen_behaviour)
# Let UI know that we're connected >:)
# Let UI know that we're connected
topic = b"ping"
data = json.dumps(True).encode()
if self.pub_socket is None:
self.logger.error("communication agent pub socket not correctly initialized.")
self.logger.error("Communication agent pub socket not correctly initialized.")
else:
try:
await asyncio.wait_for(self.pub_socket.send_multipart([topic, data]), 5)
except TimeoutError:
self.logger.error(
self.logger.warning(
"Initial connection ping for router timed out in ri_communication_agent."
)