Skip to content

Commit

Permalink
feat: simplejson decode error fix
Browse files Browse the repository at this point in the history
- if simplejson is installed JSONDecodeError must be caught
- wait_until_initialized flag added
  • Loading branch information
klepo committed May 20, 2024
1 parent 7e2199e commit 6461bea
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 12 deletions.
2 changes: 1 addition & 1 deletion era_5g_client/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ python_distribution(
sdist=True,
provides=setup_py(
name="era_5g_client",
version="1.0.0",
version="1.1.0",
description="A client for 5G-ERA Network Applications",
author="Michal Kapinus",
author_email="[email protected]",
Expand Down
5 changes: 4 additions & 1 deletion era_5g_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def register(
args: Optional[Dict[str, Any]] = None,
wait_until_available: bool = False,
wait_timeout: int = -1,
wait_until_initialized: bool = True,
) -> None:
"""Wait for ready Middleware resources and connects to the 5G-ERA Network Application server DATA_NAMESPACE and
CONTROL_NAMESPACE.
Expand All @@ -173,6 +174,8 @@ def register(
until it is available. Defaults to False.
wait_timeout: How long the client will try to connect to network application. Only used if
wait_until_available is True. If negative, the client will wait indefinitely. Defaults to -1.
wait_until_initialized (bool): If True, the client will repeatedly wait for the Network Application
initialization. Defaults to True.
Raises:
NetAppNotReady: Raised when register called before the 5G-ERA Network Application is ready.
Expand All @@ -184,7 +187,7 @@ def register(
if not self.resource_checker.is_ready():
raise NetAppNotReady("Not ready.")
self.args = args
super().register(netapp_address, args, wait_until_available, wait_timeout)
super().register(netapp_address, args, wait_until_available, wait_timeout, wait_until_initialized)

@property
def switching(self) -> bool:
Expand Down
42 changes: 32 additions & 10 deletions era_5g_client/client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import socketio
import ujson
from requests import JSONDecodeError
from socketio.exceptions import ConnectionError

from era_5g_client.exceptions import FailedToConnect
Expand Down Expand Up @@ -123,12 +124,15 @@ def __init__(
# Args for registration.
self._args: Optional[Dict[str, Any]] = None

self._initialized = False # Initialization flag.

def register(
self,
netapp_address: str,
args: Optional[Dict[str, Any]] = None,
wait_until_available: bool = False,
wait_timeout: int = -1,
wait_until_initialized: bool = True,
) -> None:
"""Connects to the 5G-ERA Network Application server DATA_NAMESPACE and CONTROL_NAMESPACE.
Expand All @@ -137,13 +141,15 @@ def register(
port and path to the interface, e.g. http://localhost:80 or http://gateway/path_to_interface.
args (Dict, optional): Optional parameters to be passed to the 5G-ERA Network Application, in the form of
dict. Defaults to None.
wait_until_available: If True, the client will repeatedly try to register with the Network Application
wait_until_available (bool): If True, the client will repeatedly try to register with the Network Application
until it is available. Defaults to False.
wait_timeout: How long the client will try to connect to network application. Only used if
wait_timeout (int): How long the client will try to connect to Network Application. Only used if
wait_until_available is True. If negative, the client will wait indefinitely. Defaults to -1.
wait_until_initialized (bool): If True, the client will repeatedly wait for the Network Application
initialization. Defaults to True.
Raises:
FailedToConnect: Failed to connect to network application exception.
FailedToConnect: Failed to connect to Network Application exception.
Returns:
Response: response from the 5G-ERA Network Application.
Expand All @@ -157,25 +163,31 @@ def register(
start_time = time.time()
while True:
try:
self.logger.info(f"Trying to connect to the network application: {netapp_address}")
self.logger.info(f"Trying to connect to the Network Application: {netapp_address}")
self._sio.connect(
netapp_address,
namespaces=namespaces_to_connect,
wait_timeout=10,
)
break
except ConnectionError as ex:
except (ConnectionError, JSONDecodeError) as ex:
self.logger.debug(f"Failed to connect: {repr(ex)}")
if not wait_until_available or (wait_timeout > 0 and start_time + wait_timeout < time.time()):
raise FailedToConnect(ex)
self.logger.warning("Failed to connect to network application. Retrying in 1 second.")
self.logger.warning("Failed to connect to Network Application. Retrying in 1 second.")
time.sleep(1)

self.logger.info(f"Client connected to namespaces: {namespaces_to_connect}")

if wait_until_initialized:
while not self._initialized:
self.logger.warning("Waiting for successful initialization by INIT command. Retrying in 1 second.")
time.sleep(1)

def disconnect(self) -> None:
"""Disconnects the WebSocket connection."""

self._initialized = False
if self._sio.connected:
self._sio.disconnect()

Expand All @@ -197,6 +209,15 @@ def wait(self) -> None:

self._sio.wait()

@property
def initialized(self) -> bool:
"""Is the Network Application initialized by ControlCmdType.INIT?
Returns: True if Network Application was initialized, False otherwise.
"""

return self._initialized

def data_connect_callback(self) -> None:
"""The callback called once the connection to the 5G-ERA Network Application DATA_NAMESPACE is made."""

Expand All @@ -212,16 +233,17 @@ def control_connect_callback(self) -> None:
f"{self._channels.get_client_eio_sid(CONTROL_NAMESPACE)}"
)

# Initialize the network application with desired parameters using the init command.
self._initialized = False
# Initialize the Network Application with desired parameters using the init command.
control_command = ControlCommand(ControlCmdType.INIT, clear_queue=False, data=self._args)
self.logger.info(f"Initialize the network application using the init command {control_command}")
self.logger.info(f"Initialize the Network Application using the INIT command {control_command}")
initialized, message = self.send_control_command(control_command)
if not initialized:
self.disconnect()
self.logger.error(f"Failed to initialize the network application: {message}")
self.logger.error(f"Failed to initialize the Network Application: {message}")
logging.shutdown() # should flush the logger
os._exit(1)
# raise FailedToInitialize(f"Failed to initialize the network application: {message}")
self._initialized = True

def data_disconnect_callback(self) -> None:
"""The callback called once the connection to the 5G-ERA Network Application DATA_NAMESPACE is lost."""
Expand Down

0 comments on commit 6461bea

Please sign in to comment.