Skip to content

Commit 43d5455

Browse files
authored
Merge pull request #53 from GabyUnalaq/connection_problems_fix
Connection problems fix
2 parents 5776cad + c24809a commit 43d5455

18 files changed

Lines changed: 429 additions & 224 deletions

File tree

ankaios_sdk/_components/control_interface.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
- Change the state of the control interface.
4343
.. code-block:: python
4444
45-
ci.change_state(ControlInterfaceState.CONNECTED)
45+
ci.change_state(ControlInterfaceState.TERMINATED)
4646
"""
4747

4848

@@ -60,7 +60,7 @@
6060

6161
from .._protos import _control_api
6262
from .request import Request
63-
from .response import Response, ResponseException
63+
from .response import Response, ResponseException, ResponseType
6464
from ..exceptions import ControlInterfaceException, ConnectionClosedException
6565
from ..utils import DEFAULT_CONTROL_INTERFACE_PATH, get_logger, ANKAIOS_VERSION
6666

@@ -208,18 +208,24 @@ def _cleanup(self) -> None:
208208
self._input_file = None
209209
self._logger.debug("Cleanup happened")
210210

211-
def change_state(self, state: ControlInterfaceState) -> None:
211+
def change_state(
212+
self, state: ControlInterfaceState, info: str = None
213+
) -> None:
212214
"""
213215
Change the state of the control interface.
214216
215217
Args:
216218
state (ControlInterfaceState): The new state.
219+
info (str): Additional information about the state change.
217220
"""
218221
if state == self._state:
219222
self._logger.debug("State is already %s.", state)
220223
return
224+
if self._state == ControlInterfaceState.CONNECTION_CLOSED:
225+
self._logger.debug("State CONNECTION_CLOSED is unrecoverable.")
226+
return
221227
self._state = state
222-
self._state_changed_callback(state)
228+
self._state_changed_callback(state, info)
223229

224230
# pylint: disable=too-many-statements, too-many-branches
225231
def _read_from_control_interface(self) -> None:
@@ -298,12 +304,15 @@ def _read_from_control_interface(self) -> None:
298304
except ResponseException as e: # pragma: no cover
299305
self._logger.error("Error while reading: %s", e)
300306
continue
301-
except ConnectionClosedException as e: # pragma: no cover
302-
self._logger.error("Connection closed: %s", e)
303-
self.change_state(ControlInterfaceState.CONNECTION_CLOSED)
304-
break
305307

306308
self._add_response_callback(response)
309+
310+
if response.content_type == ResponseType.CONNECTION_CLOSED:
311+
self.change_state(
312+
ControlInterfaceState.CONNECTION_CLOSED,
313+
response.content
314+
)
315+
raise ConnectionClosedException(response.content)
307316
except Exception as e: # pylint: disable=broad-exception-caught
308317
self._logger.error("Error while reading fifo file: %s", e)
309318
finally:
@@ -317,15 +326,15 @@ def _agent_gone_routine(self) -> None:
317326
It will attempt to write the hello message to the agent
318327
until the agent is connected.
319328
"""
320-
AGENT_RECONNECT_INTERVAL = 1 # seconds
329+
agent_reconnect_interval = 1 # seconds
321330
while self.state == ControlInterfaceState.AGENT_DISCONNECTED:
322331
try:
323332
self._send_initial_hello()
324333
except BrokenPipeError as _:
325334
self._logger.warning(
326335
"Waiting for the agent.."
327336
)
328-
time.sleep(AGENT_RECONNECT_INTERVAL)
337+
time.sleep(agent_reconnect_interval)
329338
else:
330339
self.change_state(ControlInterfaceState.INITIALIZED)
331340
break
@@ -364,7 +373,12 @@ def write_request(self, request: Request) -> None:
364373
365374
Raises:
366375
ControlInterfaceException: If not connected.
376+
ConnectionClosedException: If the connection is closed.
367377
"""
378+
if self._state == ControlInterfaceState.CONNECTION_CLOSED:
379+
raise ConnectionClosedException(
380+
"Could not write to pipe, connection closed."
381+
)
368382
if not self._state == ControlInterfaceState.INITIALIZED:
369383
raise ControlInterfaceException(
370384
"Could not write to pipe, not connected.")

ankaios_sdk/_components/response.py

Lines changed: 14 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,14 @@
1313
# SPDX-License-Identifier: Apache-2.0
1414

1515
"""
16-
This script defines the Response and ResponseEvent classes,
16+
This script defines the Response and UpdateStateSuccess classes,
1717
used for receiving messages from the control interface.
1818
1919
Classes
2020
--------
2121
2222
- Response:
2323
Represents a response from the control interface.
24-
- ResponseEvent:
25-
Represents an event used to wait for a response.
2624
- UpdateStateSuccess:
2725
Represents a response for a successful update state request.
2826
@@ -31,7 +29,7 @@
3129
3230
- ResponseType:
3331
Enumeration for the different types of response. It includes
34-
ERROR, COMPLETE_STATE, and UPDATE_STATE_SUCCESS.
32+
ERROR, COMPLETE_STATE, and UPDATE_STATE_SUCCESS and CONNECTION_CLOSED.
3533
3634
Usage
3735
------
@@ -56,13 +54,12 @@
5654
update_state_success.to_dict()
5755
"""
5856

59-
__all__ = ["Response", "ResponseType", "ResponseEvent", "UpdateStateSuccess"]
57+
__all__ = ["Response", "ResponseType", "UpdateStateSuccess"]
6058

6159
from typing import Union
62-
from threading import Event
6360
from enum import Enum
6461
from .._protos import _control_api
65-
from ..exceptions import ResponseException, ConnectionClosedException
62+
from ..exceptions import ResponseException
6663
from ..utils import get_logger
6764
from .complete_state import CompleteState
6865
from .workload_state import WorkloadInstanceName
@@ -95,7 +92,6 @@ def __init__(self, message_buffer: bytes) -> None:
9592
self.content = None
9693

9794
self._parse_response()
98-
self._from_proto()
9995

10096
def _parse_response(self) -> None:
10197
"""
@@ -115,12 +111,13 @@ def _parse_response(self) -> None:
115111
raise ResponseException(f"Parsing error: '{e}'") from e
116112
if from_ankaios.HasField("response"):
117113
self._response = from_ankaios.response
114+
self._from_proto()
115+
elif from_ankaios.HasField("connectionClosed"):
116+
self.content_type = ResponseType.CONNECTION_CLOSED
117+
self.content = from_ankaios.connectionClosed.reason
118118
else:
119-
logger.error(
120-
"Connection closed by the server."
121-
)
122-
raise ConnectionClosedException(
123-
from_ankaios.connectionClosed.reason)
119+
raise ResponseException( # pragma: no cover
120+
"Invalid response type.")
124121

125122
def _from_proto(self) -> None:
126123
"""
@@ -168,6 +165,8 @@ def get_request_id(self) -> str:
168165
Returns:
169166
str: The request id of the response.
170167
"""
168+
if self.content_type == ResponseType.CONNECTION_CLOSED:
169+
return None
171170
return self._response.requestId
172171

173172
def get_content(self) -> \
@@ -193,6 +192,8 @@ class ResponseType(Enum):
193192
"(int): Got the complete state."
194193
UPDATE_STATE_SUCCESS = 3
195194
"(int): Got a successful update state response."
195+
CONNECTION_CLOSED = 4
196+
"(int): Connection closed by the server."
196197

197198
def __str__(self) -> str:
198199
"""
@@ -204,60 +205,6 @@ def __str__(self) -> str:
204205
return self.name.lower()
205206

206207

207-
class ResponseEvent(Event):
208-
"""
209-
Represents an event that holds a Response object.
210-
"""
211-
def __init__(self, response: Response = None) -> None:
212-
"""
213-
Initializes the ResponseEvent with an optional Response object.
214-
215-
Args:
216-
response Optional(Response): The response to associate with
217-
the event. Defaults to None.
218-
"""
219-
super().__init__()
220-
self._response = response
221-
222-
def set_response(self, response: Response) -> None:
223-
"""
224-
Sets the response and triggers the event.
225-
226-
Args:
227-
response (Response): The response to set.
228-
"""
229-
self._response = response
230-
self.set()
231-
232-
def get_response(self) -> Response:
233-
"""
234-
Gets the response associated with the event.
235-
236-
Returns:
237-
Response: The response associated with the event.
238-
"""
239-
return self._response
240-
241-
def wait_for_response(self, timeout: int) -> Response:
242-
"""
243-
Waits for the response to be set, with a specified timeout.
244-
245-
Args:
246-
timeout (int): The maximum time to wait for the response,
247-
in seconds.
248-
249-
Returns:
250-
Response: The response associated with the event.
251-
252-
Raises:
253-
TimeoutError: If the response is not set within the
254-
specified timeout.
255-
"""
256-
if not self.wait(timeout):
257-
raise TimeoutError("Timeout while waiting for the response.")
258-
return self.get_response()
259-
260-
261208
class UpdateStateSuccess:
262209
"""
263210
Represents an object that holds the added and deleted workloads.

0 commit comments

Comments
 (0)