def error(self, action: str, params: object, result: Result) -> bool: """ Add an error entry to the database Parameters ---------- action : str A unique identifier for the action, usually ${method_name}:${class name} params : object The arguments to the method as scalar, list or dict result: metaroot.api.Result The Result of the failed operation that contains more granular information about the error Returns --------- metaroot.api.Result True for success Raises --------- Exception if the database if an underlying operation raised an exception """ return self._insert( (datetime.datetime.now(), ActivityStream.ERROR, action, yaml.safe_dump(params), result.status, yaml.safe_dump(result.to_transport_format())))
def _safe_call(self, method_name: str, args: list, target_managers="any") -> Result: """ Iterates over the list of Managers, calling manager methods that implement the API request and returning the individual and overall result. Parameters ---------- method_name: str The name of the method that should be called on each Manager args: list An ordered list of arguments that match the method signature target_managers: object Either the string "any" meaning all managers that implement the method will be called, or a list of manager class names that should be called Returns ------- Result Result.status is the overall status: 0 for success, >0 for error Result.response is a dictionary with keys that are the class names of each Manager that implements the requested method and the value of each key is the specific Result returned by the call to that Manger class method """ status = 0 all_results = {} # If operating in read-only mode, refuse all write requests if self._read_only: if "add" in method_name or "delete" in method_name or "associate" in method_name or \ "update" in method_name or "set" in method_name: result = Result( 470, "Read-only operation is enabled, but write operation requested" ) self.__activity_stream.record(method_name + ":any", args, result) return result n_priors = 0 for manager in self._managers: # Filter which mangers to target (by default all will be targeted) if target_managers == "any" or manager.__class__.__name__ in target_managers: # Find the method on the manager (skip if not defined) try: method = getattr(manager, method_name) except AttributeError as e: self._logger.debug( "Method %s is not defined for manager/hook %s", method_name, manager.__class__.__name__) continue result = method(*args) status = status + result.status all_results[ manager.__class__.__name__] = result.to_transport_format() self.__activity_stream.record( method_name + ":" + manager.__class__.__name__, args, result) # Allow reactions to occur in response to result of last action n_priors = n_priors + self._reactions.occur_in_response_to( manager.__class__.__name__, method_name, args, result, n_priors) return Result(status, all_results)