Merge "Move pom for sonar analyses into ricsdl-package"
authorTimo Tietavainen <timo.tietavainen@nokia.com>
Thu, 23 Jan 2020 15:27:26 +0000 (15:27 +0000)
committerGerrit Code Review <gerrit@o-ran-sc.org>
Thu, 23 Jan 2020 15:27:26 +0000 (15:27 +0000)
12 files changed:
docs/release-notes.rst
releases/pypi-ricsdl.yaml
ricsdl-package/examples/sync.py
ricsdl-package/ricsdl/__init__.py
ricsdl-package/ricsdl/backend/dbbackend_abc.py
ricsdl-package/ricsdl/backend/fake_dict_db.py
ricsdl-package/ricsdl/backend/redis.py
ricsdl-package/ricsdl/syncstorage.py
ricsdl-package/ricsdl/syncstorage_abc.py
ricsdl-package/tests/backend/test_fake_dict_db.py
ricsdl-package/tests/backend/test_redis.py
ricsdl-package/tests/test_syncstorage.py

index 007bf35..257c772 100644 (file)
@@ -33,6 +33,10 @@ This document provides the release notes of the ricsdl library.
 Version history
 ---------------
 
+[2.0.3] - 2020-01-22
+
+* Add a new SDL storage API function `is_active()` to check healthiness of SDL instance.
+
 [2.0.2] - 2020-01-14
 
 * Version bump.
index 6139e76..0f51c4f 100644 (file)
@@ -1,5 +1,5 @@
 ---
 pypi_project: ricsdl
 python_version: '3.7'
-version: 2.0.2
-log_dir: ric-plt-sdlpy-pypi-merge-master/7
+version: 2.0.3
+log_dir: ric-plt-sdlpy-pypi-merge-master/8
index f01369a..6ea9ef9 100644 (file)
@@ -78,6 +78,11 @@ mysdl = _try_func_return(SyncStorage)
 # database services.
 # mysdl = _try_func_return(lambda: SyncStorage(fake_db_backend='dict'))
 
+# Checks if SDL is operational. Note that it is not necessary to call `is_active()` after each
+# SDL instance creation. Below example is here just to show how to call it spontaneously
+# when SDL healthiness is needed to check.
+is_active = mysdl.is_active()
+assert is_active is True
 
 # Sets a value 'my_value' for a key 'my_key' under given namespace. Note that value
 # type must be bytes and multiple key values can be set in one set function call.
index 726caf6..8d4b484 100644 (file)
@@ -31,7 +31,7 @@ from .exceptions import (
 )
 
 
-__version__ = '2.0.2'
+__version__ = '2.0.3'
 
 
 __all__ = [
index 08f4600..4f31554 100644 (file)
@@ -28,6 +28,11 @@ from abc import ABC, abstractmethod
 class DbBackendAbc(ABC):
     """An abstract Shared Data Layer (SDL) class providing database backend interface."""
 
+    @abstractmethod
+    def is_connected(self):
+        """Test database backend connection."""
+        pass
+
     @abstractmethod
     def close(self):
         """Close database backend connection."""
index 51e6c18..b6c84a2 100644 (file)
@@ -51,6 +51,9 @@ class FakeDictBackend(DbBackendAbc):
             }
         )
 
+    def is_connected(self):
+        return True
+
     def close(self):
         pass
 
index 63972e3..3364497 100644 (file)
@@ -90,6 +90,10 @@ class RedisBackend(DbBackendAbc):
             }
         )
 
+    def is_connected(self):
+        with _map_to_sdl_exception():
+            return self.__redis.ping()
+
     def close(self):
         self.__redis.close()
 
index 41deeba..29adb17 100644 (file)
@@ -25,7 +25,7 @@ from ricsdl.configuration import _Configuration
 from ricsdl.syncstorage_abc import (SyncStorageAbc, SyncLockAbc)
 import ricsdl.backend
 from ricsdl.backend.dbbackend_abc import DbBackendAbc
-from ricsdl.exceptions import SdlTypeError
+from ricsdl.exceptions import (SdlException, SdlTypeError)
 
 
 def func_arg_checker(exception, start_arg_idx, **types):
@@ -132,6 +132,12 @@ class SyncStorage(SyncStorageAbc):
             }
         )
 
+    def is_active(self):
+        try:
+            return self.__dbbackend.is_connected()
+        except SdlException:
+            return False
+
     def close(self):
         self.__dbbackend.close()
 
index 9ccd99d..c5b15b3 100644 (file)
@@ -170,6 +170,24 @@ class SyncStorageAbc(ABC):
     A concrete implementation subclass 'SyncStorage' derives from this abstract class.
     """
 
+    @abstractmethod
+    def is_active(self):
+        """
+        Verify SDL storage healthiness.
+
+        Verify SDL connection to the backend data storage.
+
+        Args:
+            None
+
+        Returns:
+            bool: True if SDL is operational, false otherwise.
+
+        Raises:
+            None
+        """
+        pass
+
     @abstractmethod
     def close(self):
         """
index 45b0f0f..3b072e5 100644 (file)
@@ -57,6 +57,10 @@ def fake_dict_backend_fixture(request):
 
 @pytest.mark.usefixtures('fake_dict_backend_fixture')
 class TestFakeDictBackend:
+    def test_is_connected_function_success(self):
+        ret = self.db.is_connected()
+        assert ret is True
+
     def test_set_function_success(self):
         self.db.set(self.ns, self.dm)
         self.db.set(self.ns, self.dm2)
index 61b56ff..4f46205 100644 (file)
@@ -72,6 +72,23 @@ def redis_backend_fixture(request):
 
 @pytest.mark.usefixtures('redis_backend_fixture')
 class TestRedisBackend:
+    def test_is_connected_function_success(self):
+        self.mock_redis.ping.return_value = True
+        ret = self.db.is_connected()
+        self.mock_redis.ping.assert_called_once()
+        assert ret is True
+
+    def test_is_connected_function_returns_false_if_ping_fails(self):
+        self.mock_redis.ping.return_value = False
+        ret = self.db.is_connected()
+        self.mock_redis.ping.assert_called_once()
+        assert ret is False
+
+    def test_is_connected_function_can_map_redis_exception_to_sdl_exception(self):
+        self.mock_redis.ping.side_effect = redis_exceptions.ResponseError('redis error!')
+        with pytest.raises(ricsdl.exceptions.RejectedByBackend):
+            self.db.is_connected()
+
     def test_set_function_success(self):
         self.db.set(self.ns, self.dm)
         self.mock_redis.mset.assert_called_once_with(self.dm_redis)
index 00d3ed8..29fd5d4 100644 (file)
@@ -24,7 +24,7 @@ import pytest
 from ricsdl.syncstorage import SyncStorage
 from ricsdl.syncstorage import SyncLock
 from ricsdl.syncstorage import func_arg_checker
-from ricsdl.exceptions import SdlTypeError
+from ricsdl.exceptions import (SdlTypeError, NotConnected)
 
 
 @pytest.fixture()
@@ -53,6 +53,18 @@ def sync_storage_fixture(request):
 
 @pytest.mark.usefixtures('sync_storage_fixture')
 class TestSyncStorage:
+    def test_is_active_function_success(self):
+        self.mock_db_backend.is_connected.return_value = True
+        ret = self.storage.is_active()
+        self.mock_db_backend.is_connected.assert_called_once()
+        assert ret is True
+
+    def test_is_active_function_can_catch_backend_exception_and_return_false(self):
+        self.mock_db_backend.is_connected.side_effect = NotConnected
+        ret = self.storage.is_active()
+        self.mock_db_backend.is_connected.assert_called_once()
+        assert ret is False
+
     def test_set_function_success(self):
         self.storage.set(self.ns, self.dm)
         self.mock_db_backend.set.assert_called_once_with(self.ns, self.dm)