Towards a1 1.0.0: rmr improvements
[ric-plt/a1.git] / a1 / data.py
index 6fa8b3f..d701373 100644 (file)
@@ -23,8 +23,10 @@ Hopefully, the access functions are a good api so nothing else has to change whe
 For now, the database is in memory.
 We use dict data structures (KV) with the expectation of having to move this into Redis
 """
+import json
 from a1.exceptions import PolicyTypeNotFound, PolicyInstanceNotFound, PolicyTypeAlreadyExists
 from a1 import get_module_logger
+from a1 import a1rmr
 
 logger = get_module_logger(__name__)
 
@@ -35,6 +37,7 @@ I = "instances"
 H = "handlers"
 D = "data"
 
+
 # Types
 
 
@@ -67,6 +70,13 @@ def get_policy_type(policy_type_id):
     return POLICY_DATA[policy_type_id][D]
 
 
+def get_type_list():
+    """
+    retrieve all type ids
+    """
+    return list(POLICY_DATA.keys())
+
+
 # Instances
 
 
@@ -92,11 +102,45 @@ def store_policy_instance(policy_type_id, policy_instance_id, instance):
     POLICY_DATA[policy_type_id][I][policy_instance_id][H] = {}
 
 
+def delete_policy_instance_if_applicable(policy_type_id, policy_instance_id):
+    """
+    delete a policy instance if all known statuses are DELETED
+
+    pops a1s waiting mailbox
+    """
+    # pop through a1s mailbox, updating a1s db of all policy statuses
+    for msg in a1rmr.dequeue_all_waiting_messages([21024]):
+        # try to parse the messages as responses. Drop those that are malformed
+        # NOTE: we don't use the parameters "policy_type_id, policy_instance" from above here,
+        # because we are popping the whole mailbox, which might include other statuses
+        pay = json.loads(msg["payload"])
+        if "policy_type_id" in pay and "policy_instance_id" in pay and "handler_id" in pay and "status" in pay:
+            set_policy_instance_status(pay["policy_type_id"], pay["policy_instance_id"], pay["handler_id"], pay["status"])
+        else:
+            logger.debug("Dropping message")
+            logger.debug(pay)
+
+    # raise if not valid
+    instance_is_valid(policy_type_id, policy_instance_id)
+
+    # see if we can delete
+    vector = get_policy_instance_statuses(policy_type_id, policy_instance_id)
+    if vector != []:
+        all_deleted = True
+        for i in vector:
+            if i != "DELETED":
+                all_deleted = False
+                break  # have at least one not DELETED, do nothing
+
+        # blow away from a1 db
+        if all_deleted:
+            del POLICY_DATA[policy_type_id][I][policy_instance_id]
+
+
 def get_policy_instance(policy_type_id, policy_instance_id):
     """
     Retrieve a policy instance
     """
-    type_is_valid(policy_type_id)
     instance_is_valid(policy_type_id, policy_instance_id)
     return POLICY_DATA[policy_type_id][I][policy_instance_id][D]
 
@@ -105,17 +149,23 @@ def get_policy_instance_statuses(policy_type_id, policy_instance_id):
     """
     Retrieve the status vector for a policy instance
     """
-    type_is_valid(policy_type_id)
     instance_is_valid(policy_type_id, policy_instance_id)
 
-    return [{"handler_id": k, "status": v} for k, v in POLICY_DATA[policy_type_id][I][policy_instance_id][H].items()]
+    return [v for _, v in POLICY_DATA[policy_type_id][I][policy_instance_id][H].items()]
 
 
 def set_policy_instance_status(policy_type_id, policy_instance_id, handler_id, status):
     """
     Update the status of a handler id of a policy instance
     """
-    type_is_valid(policy_type_id)
     instance_is_valid(policy_type_id, policy_instance_id)
 
     POLICY_DATA[policy_type_id][I][policy_instance_id][H][handler_id] = status
+
+
+def get_instance_list(policy_type_id):
+    """
+    retrieve all instance ids for a type
+    """
+    type_is_valid(policy_type_id)
+    return list(POLICY_DATA[policy_type_id][I].keys())