Read list type of environment variables
[ric-plt/sdlpy.git] / ricsdl-package / examples / notify.py
index 7d2f203..47d9b04 100755 (executable)
@@ -23,11 +23,11 @@ Execution of  these examples requires:
  * Following Redis extension commands have been installed to runtime environment:
    - MSETPUB
    - SETIE
-   - SETIEPUB
-   - SETNXPUB
-   - DELPUB
+   - SETIEMPUB
+   - SETNXMPUB
+   - DELMPUB
    - DELIE
-   - DELIEPUB
+   - DELIEMPUB
    Redis v4.0 or greater is required. Older versions do not support extension modules.
    Implementation of above commands is produced by RIC DBaaS:
    https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/dbaas
@@ -37,11 +37,22 @@ Execution of  these examples requires:
    running Redis.
  * Following environment variables are needed to set to the pod/container where the application
    utilizing SDL is going to be run.
-     DBAAS_SERVICE_HOST = [redis server address]
-     DBAAS_SERVICE_PORT= [redis server port]
-     DBAAS_MASTER_NAME = [master Redis sentinel name]. Needed to set only if sentinel is in use.
-     DBAAS_SERVICE_SENTINEL_PORT = [Redis sentinel port number]. Needed to set only if sentinel
-     is in use.
+     DBAAS_SERVICE_HOST = [DB service address]
+     DBAAS_SERVICE_PORT= [Comma separated list of DB service ports]. Only one port supported in
+     RIC deployments, Nokia SEP deployments can have multiple ports.
+     DBAAS_MASTER_NAME = [Comma separated list of DB names]. Needed to set only if Redis
+     sentinel is used to provide high availability for Redis DB solution. Only one DB name
+     supported in RIC deployments, Nokia SEP deployments can have multiple DB names.
+     DBAAS_SERVICE_SENTINEL_PORT = [Comma separated list of Redis sentinel port number]. Needed
+     to set only if Redis sentinel is in use. Only one port supported in RIC deployments, Nokia
+     SEP deployments can have multiple ports.
+     DBASS_CLUSTER_ADDR_LIST = [Comma separated list of DB service addresses]. Is set only if
+     more than one Redis sentinel groups are in use. Only in use in Nokia SEP deployments.
+   In official RIC deployments four first environment variables are defined in Helm configMaps
+   of the DBaaS and these configurations can be loaded automatically as environment variables
+   into application pods via `envFrom dbaas-appconfig` statement in an application Helm Charts.
+   The last environment variable is not for time being in use in official RIC deployments, only
+   in Nokia SEP deployments.
 """
 
 import threading
@@ -49,13 +60,14 @@ import time
 
 from ricsdl.syncstorage import SyncStorage
 from ricsdl.exceptions import RejectedByBackend, NotConnected, BackendError
+from typing import (Union, List)
 
 # There are two available methods for applications to handle notifications:
 #   - EVENT_LISTENER (true):
 #     - User calls sdl.start_event_listener() which will create an SDL managed
 #       event loop for handling messages.
 #   - EVENT_LISTENER (false):
-#     - User need to call sdl.handle_messages() which will return the message
+#     - User need to call sdl.handle_events() which will return the message
 #
 # Note: In both cases, the given callback function will be executed.
 EVENT_LISTENER = True
@@ -106,8 +118,8 @@ last_cb_message = ""
 stop_thread = False
 
 
-def cb(channel: str, message: str):
-    """An example of function that will be called when an event is received.
+def cb(channel: str, message: List[str]):
+    """An example of function that will be called when an event list is received.
 
     This function sets last_cb_channel and last_cb_message as channel and
     message respectively. This also unlocks the global lock variable.
@@ -134,6 +146,9 @@ def listen_thread():
             pass
         time.sleep(0.001)
 
+# Subscribe to MY_CHANNEL. We expect that anytime we receive a message in the
+# channel, cb function will be called.
+_try_func_return(lambda: mysdl.subscribe_channel(MY_NS, cb, MY_CHANNEL))
 
 # As mentioned above, there are two available methods for applications to
 # handle notifications
@@ -143,22 +158,25 @@ else:
     thread = threading.Thread(target=listen_thread)
     thread.start()
 
-# Subscribe to MY_CHANNEL. We expect that anytime we receive a message in the
-# channel, cb function will be called.
-_try_func_return(lambda: mysdl.subscribe_channel(MY_NS, cb, MY_CHANNEL))
-
 # 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.
 _try_func_callback_return(
     lambda: mysdl.set_and_publish(MY_NS, {MY_CHANNEL: "SET PUBLISH"}, {'my_key': b'my_value'}))
-assert last_cb_channel == MY_CHANNEL and last_cb_message == "SET PUBLISH"
+assert last_cb_channel == MY_CHANNEL and last_cb_message[0] == "SET PUBLISH"
+
+# 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.
+# Function publishes two events into one channel.
+_try_func_callback_return(
+    lambda: mysdl.set_and_publish(MY_NS, {MY_CHANNEL: ["SET PUBLISH1", "SET PUBLISH2"]}, {'my_key': b'my_value'}))
+assert last_cb_channel == MY_CHANNEL and last_cb_message == ["SET PUBLISH1", "SET PUBLISH2"]
 
 # Sets a value 'my_value2' for a key 'my_key' under given namespace only if the old value is
 # 'my_value'.
 was_set = _try_func_callback_return(lambda: mysdl.set_if_and_publish(
     MY_NS, {MY_CHANNEL: "SET IF PUBLISH"}, 'my_key', b'my_value', b'my_value2'))
 assert was_set is True
-assert last_cb_channel == MY_CHANNEL and last_cb_message == "SET IF PUBLISH"
+assert last_cb_channel == MY_CHANNEL and last_cb_message[0] == "SET IF PUBLISH"
 # Try again. This time value 'my_value2' won't be set, because the key has already 'my_value2'
 # value. Callback function will not be called here.
 was_set = _try_func_return(lambda: mysdl.set_if_and_publish(MY_NS, {MY_CHANNEL: "SET IF PUBLISH"},
@@ -170,7 +188,7 @@ assert was_set is False
 was_set = _try_func_callback_return(lambda: mysdl.set_if_not_exists_and_publish(
     MY_NS, {MY_CHANNEL: "SET IF NOT PUBLISH"}, 'my_key2', b'my_value'))
 assert was_set is True
-assert last_cb_channel == MY_CHANNEL and last_cb_message == "SET IF NOT PUBLISH"
+assert last_cb_channel == MY_CHANNEL and last_cb_message[0] == "SET IF NOT PUBLISH"
 # Try again. This time the key 'my_key2' already exists. Callback function will not be called here.
 was_set = _try_func_return(lambda: mysdl.set_if_not_exists_and_publish(
     MY_NS, {MY_CHANNEL: "SET IF NOT PUBLISH"}, 'my_key2', b'my_value'))
@@ -181,13 +199,13 @@ _try_func_callback_return(
     lambda: mysdl.remove_and_publish(MY_NS, {MY_CHANNEL: "REMOVE PUBLISH"}, 'my_key'))
 my_ret_dict = _try_func_return(lambda: mysdl.get(MY_NS, 'my_key'))
 assert my_ret_dict == {}
-assert last_cb_channel == MY_CHANNEL and last_cb_message == "REMOVE PUBLISH"
+assert last_cb_channel == MY_CHANNEL and last_cb_message[0] == "REMOVE PUBLISH"
 
 # Removes a key 'my_key' under given namespace only if the old value is 'my_value'.
 was_removed = _try_func_callback_return(lambda: mysdl.remove_if_and_publish(
     MY_NS, {MY_CHANNEL: "REMOVE IF PUBLISH"}, 'my_key2', b'my_value'))
 assert was_removed is True
-assert last_cb_channel == MY_CHANNEL and last_cb_message == "REMOVE IF PUBLISH"
+assert last_cb_channel == MY_CHANNEL and last_cb_message[0] == "REMOVE IF PUBLISH"
 # Try again to remove not anymore existing key 'my_key'. Callback function will not be called here.
 was_removed = _try_func_return(lambda: mysdl.remove_if_and_publish(
     MY_NS, {MY_CHANNEL: "REMOVE IF PUBLISH"}, 'my_key2', b'my_value'))
@@ -202,7 +220,7 @@ _try_func_callback_return(
     lambda: mysdl.remove_all_and_publish(MY_NS, {MY_CHANNEL: "REMOVE ALL PUBLISH"}))
 my_ret_dict = _try_func_return(lambda: mysdl.get(MY_NS, {'my_key'}))
 assert my_ret_dict == {}
-assert last_cb_channel == MY_CHANNEL and last_cb_message == "REMOVE ALL PUBLISH"
+assert last_cb_channel == MY_CHANNEL and last_cb_message[0] == "REMOVE ALL PUBLISH"
 
 stop_thread = True
 mysdl.close()